diff options
| author | Tom Christie | 2013-02-11 12:47:56 +0000 |
|---|---|---|
| committer | Tom Christie | 2013-02-12 08:58:28 +0000 |
| commit | 09b01887f234be55c14943028330f569823b2369 (patch) | |
| tree | 6457258308dbc63a24c7a4f16b544999adc6c2b3 /rest_framework | |
| parent | aa03425c09c2eb4fc0a24276de92a320af09c33e (diff) | |
| download | django-rest-framework-09b01887f234be55c14943028330f569823b2369.tar.bz2 | |
New style object-level permission checks
Diffstat (limited to 'rest_framework')
| -rw-r--r-- | rest_framework/generics.py | 2 | ||||
| -rw-r--r-- | rest_framework/permissions.py | 27 | ||||
| -rw-r--r-- | rest_framework/renderers.py | 2 | ||||
| -rw-r--r-- | rest_framework/tests/permissions.py | 4 | ||||
| -rw-r--r-- | rest_framework/tests/renderers.py | 2 | ||||
| -rw-r--r-- | rest_framework/views.py | 18 |
6 files changed, 41 insertions, 14 deletions
diff --git a/rest_framework/generics.py b/rest_framework/generics.py index 5abb915b..19dca7e6 100644 --- a/rest_framework/generics.py +++ b/rest_framework/generics.py @@ -131,7 +131,7 @@ class SingleObjectAPIView(SingleObjectMixin, GenericAPIView): Override default to add support for object-level permissions. """ obj = super(SingleObjectAPIView, self).get_object(queryset) - if not self.has_permission(self.request, obj): + if not self.has_object_permission(self.request, obj): self.permission_denied(self.request) return obj diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index c9bbf4c4..306f00ca 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -2,6 +2,8 @@ Provides a set of pluggable permission policies. """ from __future__ import unicode_literals +import inspect +import warnings SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS'] @@ -11,11 +13,22 @@ 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. """ - raise NotImplementedError(".has_permission() must be overridden.") + return True + + def has_object_permission(self, request, view, obj): + """ + Return `True` if permission is granted, `False` otherwise. + """ + 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 +38,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 +47,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 +58,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 +69,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()): @@ -100,7 +113,7 @@ 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 diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 960d4849..e7df8758 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -301,7 +301,7 @@ class BrowsableAPIRenderer(BaseRenderer): request = clone_request(request, method) try: - if not view.has_permission(request, obj): + if not view.has_permission(request): return # Don't have permission except Exception: return # Don't have permission and exception explicitly raise diff --git a/rest_framework/tests/permissions.py b/rest_framework/tests/permissions.py index 26a34319..b8e1d89c 100644 --- a/rest_framework/tests/permissions.py +++ b/rest_framework/tests/permissions.py @@ -115,9 +115,7 @@ class OwnerModel(models.Model): class IsOwnerPermission(permissions.BasePermission): - def has_permission(self, request, view, obj=None): - if not obj: - return True + def has_object_permission(self, request, view, obj): return request.user == obj.owner diff --git a/rest_framework/tests/renderers.py b/rest_framework/tests/renderers.py index 72405336..e3f45ce6 100644 --- a/rest_framework/tests/renderers.py +++ b/rest_framework/tests/renderers.py @@ -95,7 +95,7 @@ urlpatterns = patterns('', class POSTDeniedPermission(permissions.BasePermission): - def has_permission(self, request, view, obj=None): + def has_permission(self, request, view): return request.method != 'POST' diff --git a/rest_framework/views.py b/rest_framework/views.py index fd6b4313..dd8889ae 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -13,6 +13,7 @@ from rest_framework.response import Response from rest_framework.request import Request from rest_framework.settings import api_settings import re +import warnings def _remove_trailing_string(content, trailing): @@ -261,8 +262,23 @@ class APIView(View): """ Return `True` if the request should be permitted. """ + if obj is not None: + 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_object_permission(request, obj) + + for permission in self.get_permissions(): + if not permission.has_permission(request, self): + return False + return True + + def has_object_permission(self, request, obj): + """ + Return `True` if the request should be permitted for a given object. + """ for permission in self.get_permissions(): - if not permission.has_permission(request, self, obj): + if not permission.has_object_permission(request, self, obj): return False return True |
