mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-26 03:23:59 +03:00
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:
parent
09b01887f2
commit
f5a0275547
|
@ -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`.
|
# Instance must have an attribute named `owner`.
|
||||||
return obj.owner == request.user
|
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
|
[cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html
|
||||||
[authentication]: authentication.md
|
[authentication]: authentication.md
|
||||||
|
|
|
@ -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.
|
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
|
## Dispatch methods
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,7 @@ class SingleObjectAPIView(SingleObjectMixin, GenericAPIView):
|
||||||
Override default to add support for object-level permissions.
|
Override default to add support for object-level permissions.
|
||||||
"""
|
"""
|
||||||
obj = super(SingleObjectAPIView, self).get_object(queryset)
|
obj = super(SingleObjectAPIView, self).get_object(queryset)
|
||||||
if not self.has_object_permission(self.request, obj):
|
self.check_object_permissions(self.request, obj)
|
||||||
self.permission_denied(self.request)
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -93,8 +93,7 @@ class UpdateModelMixin(object):
|
||||||
except Http404:
|
except Http404:
|
||||||
# If this is a PUT-as-create operation, we need to ensure that
|
# If this is a PUT-as-create operation, we need to ensure that
|
||||||
# we have relevant permissions, as if this was a POST request.
|
# we have relevant permissions, as if this was a POST request.
|
||||||
if not self.has_permission(clone_request(request, 'POST')):
|
self.check_permissions(clone_request(request, 'POST'))
|
||||||
self.permission_denied(self.request)
|
|
||||||
created = True
|
created = True
|
||||||
success_status_code = status.HTTP_201_CREATED
|
success_status_code = status.HTTP_201_CREATED
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -21,8 +21,7 @@ from rest_framework.request import clone_request
|
||||||
from rest_framework.utils import dict2xml
|
from rest_framework.utils import dict2xml
|
||||||
from rest_framework.utils import encoders
|
from rest_framework.utils import encoders
|
||||||
from rest_framework.utils.breadcrumbs import get_breadcrumbs
|
from rest_framework.utils.breadcrumbs import get_breadcrumbs
|
||||||
from rest_framework import VERSION, status
|
from rest_framework import exceptions, parsers, status, VERSION
|
||||||
from rest_framework import parsers
|
|
||||||
|
|
||||||
|
|
||||||
class BaseRenderer(object):
|
class BaseRenderer(object):
|
||||||
|
@ -299,12 +298,10 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
if not api_settings.FORM_METHOD_OVERRIDE:
|
if not api_settings.FORM_METHOD_OVERRIDE:
|
||||||
return # Cannot use form overloading
|
return # Cannot use form overloading
|
||||||
|
|
||||||
request = clone_request(request, method)
|
|
||||||
try:
|
try:
|
||||||
if not view.has_permission(request):
|
view.check_permissions(clone_request(request, method))
|
||||||
return # Don't have permission
|
except exceptions.APIException:
|
||||||
except Exception:
|
return False # Doesn't have permissions
|
||||||
return # Don't have permission and exception explicitly raise
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def serializer_to_form_fields(self, serializer):
|
def serializer_to_form_fields(self, serializer):
|
||||||
|
|
|
@ -258,33 +258,28 @@ class APIView(View):
|
||||||
return (renderers[0], renderers[0].media_type)
|
return (renderers[0], renderers[0].media_type)
|
||||||
raise
|
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():
|
for permission in self.get_permissions():
|
||||||
if not permission.has_permission(request, self):
|
if not permission.has_permission(request, self):
|
||||||
return False
|
self.permission_denied(request)
|
||||||
return True
|
|
||||||
|
|
||||||
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():
|
for permission in self.get_permissions():
|
||||||
if not permission.has_object_permission(request, self, obj):
|
if not permission.has_object_permission(request, self, obj):
|
||||||
return False
|
self.permission_denied(request)
|
||||||
return True
|
|
||||||
|
|
||||||
def check_throttles(self, request):
|
def check_throttles(self, request):
|
||||||
"""
|
"""
|
||||||
Check if request should be throttled.
|
Check if request should be throttled.
|
||||||
|
Raises an appropriate exception if the request is throttled.
|
||||||
"""
|
"""
|
||||||
for throttle in self.get_throttles():
|
for throttle in self.get_throttles():
|
||||||
if not throttle.allow_request(request, self):
|
if not throttle.allow_request(request, self):
|
||||||
|
@ -311,8 +306,7 @@ class APIView(View):
|
||||||
self.format_kwarg = self.get_format_suffix(**kwargs)
|
self.format_kwarg = self.get_format_suffix(**kwargs)
|
||||||
|
|
||||||
# Ensure that the incoming request is permitted
|
# Ensure that the incoming request is permitted
|
||||||
if not self.has_permission(request):
|
self.check_permissions(request)
|
||||||
self.permission_denied(request)
|
|
||||||
self.check_throttles(request)
|
self.check_throttles(request)
|
||||||
|
|
||||||
# Perform content negotiation and store the accepted info on the request
|
# Perform content negotiation and store the accepted info on the request
|
||||||
|
|
Loading…
Reference in New Issue
Block a user