Tidy up internal view permission checking logic.

Also document correctly - these methods are now public and will fall
under the deprecation policy from now on.
This commit is contained in:
Tom Christie 2013-02-11 13:02:20 +00:00
parent 09b01887f2
commit f5a0275547
6 changed files with 20 additions and 31 deletions

View File

@ -150,7 +150,7 @@ As well as global permissions, that are run against all incoming requests, you c
# Instance must have an attribute named `owner`.
return obj.owner == request.user
Note that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself, by calling `self.has_object_permission(request, obj)` from the view.
Note that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself. You can do so by calling `self.check_object_permissions(request, obj)` from the view once you have the object instance. This call will raise an appropriate `APIException` if any object-level permission checks fail, and will otherwise simply return.
[cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html
[authentication]: authentication.md

View File

@ -76,11 +76,11 @@ The following methods are used by REST framework to instantiate the various plug
The following methods are called before dispatching to the handler method.
### .check_permissions(...)
### .check_permissions(self, request)
### .check_throttles(...)
### .check_throttles(self, request)
### .perform_content_negotiation(...)
### .perform_content_negotiation(self, request, force=False)
## Dispatch methods

View File

@ -131,8 +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_object_permission(self.request, obj):
self.permission_denied(self.request)
self.check_object_permissions(self.request, obj)
return obj

View File

@ -93,8 +93,7 @@ class UpdateModelMixin(object):
except Http404:
# If this is a PUT-as-create operation, we need to ensure that
# we have relevant permissions, as if this was a POST request.
if not self.has_permission(clone_request(request, 'POST')):
self.permission_denied(self.request)
self.check_permissions(clone_request(request, 'POST'))
created = True
success_status_code = status.HTTP_201_CREATED
else:

View File

@ -21,8 +21,7 @@ from rest_framework.request import clone_request
from rest_framework.utils import dict2xml
from rest_framework.utils import encoders
from rest_framework.utils.breadcrumbs import get_breadcrumbs
from rest_framework import VERSION, status
from rest_framework import parsers
from rest_framework import exceptions, parsers, status, VERSION
class BaseRenderer(object):
@ -299,12 +298,10 @@ class BrowsableAPIRenderer(BaseRenderer):
if not api_settings.FORM_METHOD_OVERRIDE:
return # Cannot use form overloading
request = clone_request(request, method)
try:
if not view.has_permission(request):
return # Don't have permission
except Exception:
return # Don't have permission and exception explicitly raise
view.check_permissions(clone_request(request, method))
except exceptions.APIException:
return False # Doesn't have permissions
return True
def serializer_to_form_fields(self, serializer):

View File

@ -258,33 +258,28 @@ class APIView(View):
return (renderers[0], renderers[0].media_type)
raise
def has_permission(self, request, obj=None):
def check_permissions(self, request):
"""
Return `True` if the request should be permitted.
Check if the request should be permitted.
Raises an appropriate exception if the request is not 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
self.permission_denied(request)
def has_object_permission(self, request, obj):
def check_object_permissions(self, request, obj):
"""
Return `True` if the request should be permitted for a given object.
Check if the request should be permitted for a given object.
Raises an appropriate exception if the request is not permitted.
"""
for permission in self.get_permissions():
if not permission.has_object_permission(request, self, obj):
return False
return True
self.permission_denied(request)
def check_throttles(self, request):
"""
Check if request should be throttled.
Raises an appropriate exception if the request is throttled.
"""
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
@ -311,8 +306,7 @@ class APIView(View):
self.format_kwarg = self.get_format_suffix(**kwargs)
# Ensure that the incoming request is permitted
if not self.has_permission(request):
self.permission_denied(request)
self.check_permissions(request)
self.check_throttles(request)
# Perform content negotiation and store the accepted info on the request