Commit 4692374e by Tom Christie

Generic permissions added, allowed_methods and anon_allowed_methods now defunct,…

Generic permissions added, allowed_methods and anon_allowed_methods now defunct, dispatch now mirrors View.dispatch more nicely
parent cb4b4f6b
......@@ -13,10 +13,10 @@ import base64
class BaseAuthenticator(object):
"""All authenticators should extend BaseAuthenticator."""
def __init__(self, mixin):
def __init__(self, view):
"""Initialise the authenticator with the mixin instance as state,
in case the authenticator needs to access any metadata on the mixin object."""
self.mixin = mixin
self.view = view
def authenticate(self, request):
"""Authenticate the request and return the authentication context or None.
......@@ -61,11 +61,13 @@ class BasicAuthenticator(BaseAuthenticator):
class UserLoggedInAuthenticator(BaseAuthenticator):
"""Use Djagno's built-in request session for authentication."""
"""Use Django's built-in request session for authentication."""
def authenticate(self, request):
if getattr(request, 'user', None) and request.user.is_active:
# Temporarily request.POST with .RAW_CONTENT, so that we use our more generic request parsing
request._post = self.mixin.RAW_CONTENT
# Temporarily set request.POST to view.RAW_CONTENT,
# so that we use our more generic request parsing,
# in preference to Django's form-only request parsing.
request._post = self.view.RAW_CONTENT
resp = CsrfViewMiddleware().process_view(request, None, (), {})
del(request._post)
if resp is None: # csrf passed
......
......@@ -396,9 +396,9 @@ class ResponseMixin(object):
########## Auth Mixin ##########
class AuthMixin(object):
"""Mixin class to provide authentication and permissions."""
"""Mixin class to provide authentication and permission checking."""
authenticators = ()
permitters = ()
permissions = ()
@property
def auth(self):
......@@ -406,6 +406,14 @@ class AuthMixin(object):
self._auth = self._authenticate()
return self._auth
def _authenticate(self):
for authenticator_cls in self.authenticators:
authenticator = authenticator_cls(self)
auth = authenticator.authenticate(self.request)
if auth:
return auth
return None
# TODO?
#@property
#def user(self):
......@@ -421,15 +429,11 @@ class AuthMixin(object):
if not self.permissions:
return
auth = self.auth
for permitter_cls in self.permitters:
permitter = permission_cls(self)
permitter.permit(auth)
for permission_cls in self.permissions:
permission = permission_cls(self)
if not permission.has_permission(self.auth):
raise ErrorResponse(status.HTTP_403_FORBIDDEN,
{'detail': 'You do not have permission to access this resource. ' +
'You may need to login or otherwise authenticate the request.'})
def _authenticate(self):
for authenticator_cls in self.authenticators:
authenticator = authenticator_cls(self)
auth = authenticator.authenticate(self.request)
if auth:
return auth
return None
......@@ -410,13 +410,13 @@ class ModelResource(Resource):
class RootModelResource(ModelResource):
"""A Resource which provides default operations for list and create."""
allowed_methods = ('GET', 'POST')
queryset = None
def get(self, request, *args, **kwargs):
queryset = self.queryset if self.queryset else self.model.objects.all()
return queryset.filter(**kwargs)
put = delete = http_method_not_allowed
class QueryModelResource(ModelResource):
"""Resource with default operations for list.
......@@ -424,10 +424,8 @@ class QueryModelResource(ModelResource):
allowed_methods = ('GET',)
queryset = None
def get_form(self, data=None):
return None
def get(self, request, *args, **kwargs):
queryset = self.queryset if self.queryset else self.model.objects.all()
return queryset.filer(**kwargs)
post = put = delete = http_method_not_allowed
\ No newline at end of file
......@@ -18,10 +18,13 @@ class UserAgentMungingTest(TestCase):
http://www.gethifi.com/blog/browser-rest-http-accept-headers"""
def setUp(self):
class MockResource(Resource):
anon_allowed_methods = allowed_methods = ('GET',)
permissions = ()
def get(self, request):
return {'a':1, 'b':2, 'c':3}
self.req = RequestFactory()
self.MockResource = MockResource
self.view = MockResource.as_view()
......
......@@ -13,8 +13,6 @@ except ImportError:
import simplejson as json
class MockResource(Resource):
allowed_methods = ('POST',)
def post(self, request):
return {'a':1, 'b':2, 'c':3}
......
......@@ -16,7 +16,7 @@ class UploadFilesTests(TestCase):
file = forms.FileField
class MockResource(Resource):
allowed_methods = anon_allowed_methods = ('POST',)
permissions = ()
form = FileForm
def post(self, request, *args, **kwargs):
......
......@@ -12,7 +12,7 @@ except ImportError:
class MockResource(Resource):
"""Mock resource which simply returns a URL, so that we can ensure that reversed URLs are fully qualified"""
anon_allowed_methods = ('GET',)
permissions = ()
def get(self, request):
return reverse('another')
......@@ -28,5 +28,9 @@ class ReverseTests(TestCase):
urls = 'djangorestframework.tests.reverse'
def test_reversed_urls_are_fully_qualified(self):
response = self.client.get('/')
try:
response = self.client.get('/')
except:
import traceback
traceback.print_exc()
self.assertEqual(json.loads(response.content), 'http://testserver/another')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment