mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 13:14:30 +03:00
Refactoring of authentication/permissions
This commit is contained in:
parent
941742593c
commit
cb9fb6ef2f
|
@ -10,26 +10,6 @@ from djangorestframework.utils import as_tuple
|
|||
import base64
|
||||
|
||||
|
||||
class AuthenticatorMixin(object):
|
||||
"""Adds pluggable authentication behaviour."""
|
||||
|
||||
"""The set of authenticators to use."""
|
||||
authenticators = None
|
||||
|
||||
def authenticate(self, request):
|
||||
"""Attempt to authenticate the request, returning an authentication context or None.
|
||||
An authentication context may be any object, although in many cases it will simply be a :class:`User` instance."""
|
||||
|
||||
# Attempt authentication against each authenticator in turn,
|
||||
# and return None if no authenticators succeed in authenticating the request.
|
||||
for authenticator in as_tuple(self.authenticators):
|
||||
auth_context = authenticator(self).authenticate(request)
|
||||
if auth_context:
|
||||
return auth_context
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class BaseAuthenticator(object):
|
||||
"""All authenticators should extend BaseAuthenticator."""
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ from django.http.multipartparser import LimitBytes
|
|||
from StringIO import StringIO
|
||||
|
||||
class RequestMixin(object):
|
||||
"""Mixin behaviour to deal with requests."""
|
||||
"""Mixin class to provide request parsing behaviour."""
|
||||
|
||||
USE_FORM_OVERLOADING = True
|
||||
METHOD_PARAM = "_method"
|
||||
|
@ -214,3 +214,42 @@ class RequestMixin(object):
|
|||
|
||||
|
||||
|
||||
class AuthMixin(object):
|
||||
"""Mixin class to provide authentication and permissions."""
|
||||
authenticators = ()
|
||||
permitters = ()
|
||||
|
||||
@property
|
||||
def auth(self):
|
||||
if not hasattr(self, '_auth'):
|
||||
self._auth = self._authenticate()
|
||||
return self._auth
|
||||
|
||||
# TODO?
|
||||
#@property
|
||||
#def user(self):
|
||||
# if not has_attr(self, '_user'):
|
||||
# auth = self.auth
|
||||
# if isinstance(auth, User...):
|
||||
# self._user = auth
|
||||
# else:
|
||||
# self._user = getattr(auth, 'user', None)
|
||||
# return self._user
|
||||
|
||||
def check_permissions(self):
|
||||
if not self.permissions:
|
||||
return
|
||||
|
||||
auth = self.auth
|
||||
for permitter_cls in self.permitters:
|
||||
permitter = permission_cls(self)
|
||||
permitter.permit(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
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from djangorestframework.emitters import EmitterMixin
|
|||
from djangorestframework.authenticators import AuthenticatorMixin
|
||||
from djangorestframework.validators import FormValidatorMixin
|
||||
from djangorestframework.response import Response, ResponseException
|
||||
from djangorestframework.request import RequestMixin
|
||||
from djangorestframework.request import RequestMixin, AuthMixin
|
||||
from djangorestframework import emitters, parsers, authenticators, status
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@ from djangorestframework import emitters, parsers, authenticators, status
|
|||
__all__ = ['Resource']
|
||||
|
||||
|
||||
class Resource(EmitterMixin, AuthenticatorMixin, FormValidatorMixin, RequestMixin, View):
|
||||
class Resource(EmitterMixin, AuthMixin, FormValidatorMixin, RequestMixin, View):
|
||||
"""Handles incoming requests and maps them to REST operations,
|
||||
performing authentication, input deserialization, input validation, output serialization."""
|
||||
|
||||
|
@ -139,7 +139,7 @@ class Resource(EmitterMixin, AuthenticatorMixin, FormValidatorMixin, RequestMixi
|
|||
# Typically the context will be a user, or None if this is an anonymous request,
|
||||
# but it could potentially be more complex (eg the context of a request key which
|
||||
# has been signed against a particular set of permissions)
|
||||
auth_context = self.authenticate(request)
|
||||
auth_context = self.auth
|
||||
|
||||
# If using a form POST with '_method'/'_content'/'_content_type' overrides, then alter
|
||||
# self.method, self.content_type, self.CONTENT appropriately.
|
||||
|
@ -173,6 +173,10 @@ class Resource(EmitterMixin, AuthenticatorMixin, FormValidatorMixin, RequestMixi
|
|||
|
||||
except ResponseException, exc:
|
||||
response = exc.response
|
||||
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
# Always add these headers.
|
||||
#
|
||||
|
|
|
@ -8,7 +8,7 @@ class NoContent(object):
|
|||
"""Used to indicate no body in http response.
|
||||
(We cannot just use None, as that is a valid, serializable response object.)
|
||||
|
||||
TODO: On relflection I'm going to get rid of this and just not support serailized 'None' responses.
|
||||
TODO: On reflection I'm going to get rid of this and just not support serialized 'None' responses.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
@ -23,8 +23,8 @@ class Response(object):
|
|||
|
||||
@property
|
||||
def status_text(self):
|
||||
"""Return reason text corrosponding to our HTTP response status code.
|
||||
Provided for convienience."""
|
||||
"""Return reason text corresponding to our HTTP response status code.
|
||||
Provided for convenience."""
|
||||
return STATUS_CODE_TEXT.get(self.status, '')
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user