aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/api-guide/serializers.md2
-rw-r--r--docs/api-guide/viewsets.md2
-rw-r--r--docs/topics/credits.md2
-rw-r--r--rest_framework/authentication.py5
-rw-r--r--rest_framework/routers.py3
-rw-r--r--rest_framework/tests/test_authentication.py41
-rw-r--r--rest_framework/tests/test_routers.py16
-rw-r--r--rest_framework/views.py4
8 files changed, 66 insertions, 9 deletions
diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md
index 71f0abb7..9b6a547f 100644
--- a/docs/api-guide/serializers.md
+++ b/docs/api-guide/serializers.md
@@ -39,7 +39,7 @@ Declaring a serializer looks very similar to declaring a form:
an existing model instance, or create a new model instance.
"""
if instance is not None:
- instance.title = attrs.get('title', instance.title)
+ instance.email = attrs.get('email', instance.email)
instance.content = attrs.get('content', instance.content)
instance.created = attrs.get('created', instance.created)
return instance
diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md
index 2783da98..79257e2a 100644
--- a/docs/api-guide/viewsets.md
+++ b/docs/api-guide/viewsets.md
@@ -209,8 +209,6 @@ To create a base viewset class that provides `create`, `list` and `retrieve` ope
mixins.ListMixin,
mixins.RetrieveMixin,
viewsets.GenericViewSet):
- pass
-
"""
A viewset that provides `retrieve`, `update`, and `list` actions.
diff --git a/docs/topics/credits.md b/docs/topics/credits.md
index db522922..b4bd3561 100644
--- a/docs/topics/credits.md
+++ b/docs/topics/credits.md
@@ -140,6 +140,7 @@ The following people have helped make REST framework great.
* Alex Burgel - [aburgel]
* David Medina - [copitux]
* Areski Belaid - [areski]
+* Ethan Freman - [mindlace]
Many thanks to everyone who's contributed to the project.
@@ -316,3 +317,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter.
[aburgel]: https://github.com/aburgel
[copitux]: https://github.com/copitux
[areski]: https://github.com/areski
+[mindlace]: https://github.com/mindlace
diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py
index 9caca788..f659a172 100644
--- a/rest_framework/authentication.py
+++ b/rest_framework/authentication.py
@@ -230,8 +230,9 @@ class OAuthAuthentication(BaseAuthentication):
try:
consumer_key = oauth_request.get_parameter('oauth_consumer_key')
consumer = oauth_provider_store.get_consumer(request, oauth_request, consumer_key)
- except oauth_provider.store.InvalidConsumerError as err:
- raise exceptions.AuthenticationFailed(err)
+ except oauth_provider.store.InvalidConsumerError:
+ msg = 'Invalid consumer token: %s' % oauth_request.get_parameter('oauth_consumer_key')
+ raise exceptions.AuthenticationFailed(msg)
if consumer.status != oauth_provider.consts.ACCEPTED:
msg = 'Invalid consumer key status: %s' % consumer.get_status_display()
diff --git a/rest_framework/routers.py b/rest_framework/routers.py
index 9764e569..f70c2cdb 100644
--- a/rest_framework/routers.py
+++ b/rest_framework/routers.py
@@ -215,6 +215,7 @@ class DefaultRouter(SimpleRouter):
"""
include_root_view = True
include_format_suffixes = True
+ root_view_name = 'api-root'
def get_api_root_view(self):
"""
@@ -244,7 +245,7 @@ class DefaultRouter(SimpleRouter):
urls = []
if self.include_root_view:
- root_url = url(r'^$', self.get_api_root_view(), name='api-root')
+ root_url = url(r'^$', self.get_api_root_view(), name=self.root_view_name)
urls.append(root_url)
default_urls = super(DefaultRouter, self).get_urls()
diff --git a/rest_framework/tests/test_authentication.py b/rest_framework/tests/test_authentication.py
index d46ac079..6a50be06 100644
--- a/rest_framework/tests/test_authentication.py
+++ b/rest_framework/tests/test_authentication.py
@@ -428,6 +428,47 @@ class OAuthTests(TestCase):
response = self.csrf_client.post('/oauth-with-scope/', params)
self.assertEqual(response.status_code, 200)
+ @unittest.skipUnless(oauth_provider, 'django-oauth-plus not installed')
+ @unittest.skipUnless(oauth, 'oauth2 not installed')
+ def test_bad_consumer_key(self):
+ """Ensure POSTing using HMAC_SHA1 signature method passes"""
+ params = {
+ 'oauth_version': "1.0",
+ 'oauth_nonce': oauth.generate_nonce(),
+ 'oauth_timestamp': int(time.time()),
+ 'oauth_token': self.token.key,
+ 'oauth_consumer_key': 'badconsumerkey'
+ }
+
+ req = oauth.Request(method="POST", url="http://testserver/oauth/", parameters=params)
+
+ signature_method = oauth.SignatureMethod_HMAC_SHA1()
+ req.sign_request(signature_method, self.consumer, self.token)
+ auth = req.to_header()["Authorization"]
+
+ response = self.csrf_client.post('/oauth/', HTTP_AUTHORIZATION=auth)
+ self.assertEqual(response.status_code, 401)
+
+ @unittest.skipUnless(oauth_provider, 'django-oauth-plus not installed')
+ @unittest.skipUnless(oauth, 'oauth2 not installed')
+ def test_bad_token_key(self):
+ """Ensure POSTing using HMAC_SHA1 signature method passes"""
+ params = {
+ 'oauth_version': "1.0",
+ 'oauth_nonce': oauth.generate_nonce(),
+ 'oauth_timestamp': int(time.time()),
+ 'oauth_token': 'badtokenkey',
+ 'oauth_consumer_key': self.consumer.key
+ }
+
+ req = oauth.Request(method="POST", url="http://testserver/oauth/", parameters=params)
+
+ signature_method = oauth.SignatureMethod_HMAC_SHA1()
+ req.sign_request(signature_method, self.consumer, self.token)
+ auth = req.to_header()["Authorization"]
+
+ response = self.csrf_client.post('/oauth/', HTTP_AUTHORIZATION=auth)
+ self.assertEqual(response.status_code, 401)
class OAuth2Tests(TestCase):
"""OAuth 2.0 authentication"""
diff --git a/rest_framework/tests/test_routers.py b/rest_framework/tests/test_routers.py
index a7534f70..291142cf 100644
--- a/rest_framework/tests/test_routers.py
+++ b/rest_framework/tests/test_routers.py
@@ -6,7 +6,7 @@ from rest_framework import serializers, viewsets
from rest_framework.compat import include, patterns, url
from rest_framework.decorators import link, action
from rest_framework.response import Response
-from rest_framework.routers import SimpleRouter
+from rest_framework.routers import SimpleRouter, DefaultRouter
factory = RequestFactory()
@@ -148,3 +148,17 @@ class TestTrailingSlash(TestCase):
expected = ['^notes$', '^notes/(?P<pk>[^/]+)$']
for idx in range(len(expected)):
self.assertEqual(expected[idx], self.urls[idx].regex.pattern)
+
+class TestNameableRoot(TestCase):
+ def setUp(self):
+ class NoteViewSet(viewsets.ModelViewSet):
+ model = RouterTestModel
+ self.router = DefaultRouter()
+ self.router.root_view_name = 'nameable-root'
+ self.router.register(r'notes', NoteViewSet)
+ self.urls = self.router.urls
+
+ def test_router_has_custom_name(self):
+ expected = 'nameable-root'
+ self.assertEqual(expected, self.urls[0].name)
+
diff --git a/rest_framework/views.py b/rest_framework/views.py
index 0c1ea7d7..c28d2835 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -304,10 +304,10 @@ class APIView(View):
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
- request = self.initialize_request(request, *args, **kwargs)
- self.request = request
self.args = args
self.kwargs = kwargs
+ request = self.initialize_request(request, *args, **kwargs)
+ self.request = request
self.headers = self.default_response_headers # deprecate?
try: