aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--rest_framework/permissions.py8
-rw-r--r--rest_framework/tests/authentication.py37
2 files changed, 42 insertions, 3 deletions
diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py
index 519a3691..c477474c 100644
--- a/rest_framework/permissions.py
+++ b/rest_framework/permissions.py
@@ -140,12 +140,16 @@ class TokenHasReadWriteScope(BasePermission):
read_only = request.method in SAFE_METHODS
if hasattr(request.auth, 'resource'): # oauth 1
- pass
+ if read_only:
+ return True
+ elif request.auth.resource.is_readonly is False:
+ return True
+ return False
elif hasattr(request.auth, 'scope'): # oauth 2
scope_valid = lambda scope_wanted_key, scope_had: oauth2_provider_scope.check(
oauth2_provider_scope.SCOPE_NAME_DICT[scope_wanted_key], scope_had)
- if (read_only and scope_valid('read', request.auth.scope)):
+ if read_only and scope_valid('read', request.auth.scope):
return True
elif scope_valid('write', request.auth.scope):
return True
diff --git a/rest_framework/tests/authentication.py b/rest_framework/tests/authentication.py
index 693dbb4d..b663ca48 100644
--- a/rest_framework/tests/authentication.py
+++ b/rest_framework/tests/authentication.py
@@ -47,7 +47,9 @@ urlpatterns = patterns('',
(r'^basic/$', MockView.as_view(authentication_classes=[BasicAuthentication])),
(r'^token/$', MockView.as_view(authentication_classes=[TokenAuthentication])),
(r'^auth-token/$', 'rest_framework.authtoken.views.obtain_auth_token'),
- (r'^oauth/$', MockView.as_view(authentication_classes=[OAuthAuthentication]))
+ (r'^oauth/$', MockView.as_view(authentication_classes=[OAuthAuthentication])),
+ (r'^oauth-with-scope/$', MockView.as_view(authentication_classes=[OAuthAuthentication],
+ permission_classes=[permissions.TokenHasReadWriteScope]))
)
if oauth2_provider is not None:
@@ -391,6 +393,39 @@ class OAuthTests(TestCase):
response = self.csrf_client.post('/oauth/', HTTP_AUTHORIZATION=auth)
self.assertEqual(response.status_code, 200)
+ @unittest.skipUnless(oauth_provider, 'django-oauth-plus not installed')
+ @unittest.skipUnless(oauth, 'oauth2 not installed')
+ def test_get_form_with_readonly_resource_passing_auth(self):
+ """Ensure POSTing with a readonly resource instead of a write scope fails"""
+ read_only_access_token = self.token
+ read_only_access_token.resource.is_readonly = True
+ read_only_access_token.resource.save()
+ params = self._create_authorization_url_parameters()
+ response = self.csrf_client.get('/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_post_form_with_readonly_resource_failing_auth(self):
+ """Ensure POSTing with a readonly resource instead of a write scope fails"""
+ read_only_access_token = self.token
+ read_only_access_token.resource.is_readonly = True
+ read_only_access_token.resource.save()
+ params = self._create_authorization_url_parameters()
+ response = self.csrf_client.post('/oauth-with-scope/', params)
+ self.assertIn(response.status_code, (status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN))
+
+ @unittest.skipUnless(oauth_provider, 'django-oauth-plus not installed')
+ @unittest.skipUnless(oauth, 'oauth2 not installed')
+ def test_post_form_with_write_resource_passing_auth(self):
+ """Ensure POSTing with a write resource succeed"""
+ read_write_access_token = self.token
+ read_write_access_token.resource.is_readonly = False
+ read_write_access_token.resource.save()
+ params = self._create_authorization_url_parameters()
+ response = self.csrf_client.post('/oauth-with-scope/', params)
+ self.assertEqual(response.status_code, 200)
+
class OAuth2Tests(TestCase):
"""OAuth 2.0 authentication"""