diff options
Diffstat (limited to 'rest_framework/permissions.py')
| -rw-r--r-- | rest_framework/permissions.py | 69 | 
1 files changed, 57 insertions, 12 deletions
diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 655b78a3..ae895f39 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -1,21 +1,36 @@  """  Provides a set of pluggable permission policies.  """ - +from __future__ import unicode_literals +import inspect +import warnings  SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS'] +from rest_framework.compat import oauth2_provider_scope, oauth2_constants +  class BasePermission(object):      """      A base class from which all permission classes should inherit.      """ -    def has_permission(self, request, view, obj=None): +    def has_permission(self, request, view): +        """ +        Return `True` if permission is granted, `False` otherwise. +        """ +        return True + +    def has_object_permission(self, request, view, obj):          """          Return `True` if permission is granted, `False` otherwise.          """ -        raise NotImplementedError(".has_permission() must be overridden.") +        if len(inspect.getargspec(self.has_permission)[0]) == 4: +            warnings.warn('The `obj` argument in `has_permission` is due to be deprecated. ' +                      'Use `has_object_permission()` instead for object permissions.', +                       PendingDeprecationWarning, stacklevel=2) +            return self.has_permission(request, view, obj) +        return True  class AllowAny(BasePermission): @@ -25,7 +40,7 @@ class AllowAny(BasePermission):      permission_classes list, but it's useful because it makes the intention      more explicit.      """ -    def has_permission(self, request, view, obj=None): +    def has_permission(self, request, view):          return True @@ -34,7 +49,7 @@ class IsAuthenticated(BasePermission):      Allows access only to authenticated users.      """ -    def has_permission(self, request, view, obj=None): +    def has_permission(self, request, view):          if request.user and request.user.is_authenticated():              return True          return False @@ -45,7 +60,7 @@ class IsAdminUser(BasePermission):      Allows access only to admin users.      """ -    def has_permission(self, request, view, obj=None): +    def has_permission(self, request, view):          if request.user and request.user.is_staff:              return True          return False @@ -56,7 +71,7 @@ class IsAuthenticatedOrReadOnly(BasePermission):      The request is authenticated as a user, or is a read-only request.      """ -    def has_permission(self, request, view, obj=None): +    def has_permission(self, request, view):          if (request.method in SAFE_METHODS or              request.user and              request.user.is_authenticated()): @@ -89,6 +104,8 @@ class DjangoModelPermissions(BasePermission):          'DELETE': ['%(app_label)s.delete_%(model_name)s'],      } +    authenticated_users_only = True +      def get_required_permissions(self, method, model_cls):          """          Given a model and an HTTP method, return the list of permission @@ -100,15 +117,43 @@ class DjangoModelPermissions(BasePermission):          }          return [perm % kwargs for perm in self.perms_map[method]] -    def has_permission(self, request, view, obj=None): +    def has_permission(self, request, view):          model_cls = getattr(view, 'model', None) -        if not model_cls: -            return True +        queryset = getattr(view, 'queryset', None) + +        if model_cls is None and queryset is not None: +            model_cls = queryset.model + +        assert model_cls, ('Cannot apply DjangoModelPermissions on a view that' +                           ' does not have `.model` or `.queryset` property.')          perms = self.get_required_permissions(request.method, model_cls)          if (request.user and -            request.user.is_authenticated() and -            request.user.has_perms(perms, obj)): +            (request.user.is_authenticated() or not self.authenticated_users_only) and +            request.user.has_perms(perms)):              return True          return False + + +class TokenHasReadWriteScope(BasePermission): +    """ +    The request is authenticated as a user and the token used has the right scope +    """ + +    def has_permission(self, request, view): +        token = request.auth +        read_only = request.method in SAFE_METHODS + +        if not token: +            return False + +        if hasattr(token, 'resource'):  # OAuth 1 +            return read_only or not request.auth.resource.is_readonly +        elif hasattr(token, 'scope'):  # OAuth 2 +            required = oauth2_constants.READ if read_only else oauth2_constants.WRITE +            return oauth2_provider_scope.check(required, request.auth.scope) + +        assert False, ('TokenHasReadWriteScope requires either the' +        '`OAuthAuthentication` or `OAuth2Authentication` authentication ' +        'class to be used.')  | 
