mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-26 11:33:59 +03:00
Merge pull request #2539 from donewell/permission-detail
add message to custom permission
This commit is contained in:
commit
8329411cc3
|
@ -190,6 +190,16 @@ If you need to test if a request is a read operation or a write operation, you s
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
Custom permissions will raise a `PermissionDenied` exception if the test fails. To change the error message associated with the exception, implement a `message` attribute directly on your custom permission. Otherwise the `default_detail` attribute from `PermissionDenied` will be used.
|
||||||
|
|
||||||
|
from rest_framework import permissions
|
||||||
|
|
||||||
|
class CustomerAccessPermission(permissions.BasePermission):
|
||||||
|
message = 'Adding customers not allowed.'
|
||||||
|
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
...
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
The following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted.
|
The following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted.
|
||||||
|
|
|
@ -144,13 +144,13 @@ class APIView(View):
|
||||||
"""
|
"""
|
||||||
raise exceptions.MethodNotAllowed(request.method)
|
raise exceptions.MethodNotAllowed(request.method)
|
||||||
|
|
||||||
def permission_denied(self, request):
|
def permission_denied(self, request, message=None):
|
||||||
"""
|
"""
|
||||||
If request is not permitted, determine what kind of exception to raise.
|
If request is not permitted, determine what kind of exception to raise.
|
||||||
"""
|
"""
|
||||||
if not request.successful_authenticator:
|
if not request.successful_authenticator:
|
||||||
raise exceptions.NotAuthenticated()
|
raise exceptions.NotAuthenticated()
|
||||||
raise exceptions.PermissionDenied()
|
raise exceptions.PermissionDenied(detail=message)
|
||||||
|
|
||||||
def throttled(self, request, wait):
|
def throttled(self, request, wait):
|
||||||
"""
|
"""
|
||||||
|
@ -302,7 +302,9 @@ class APIView(View):
|
||||||
"""
|
"""
|
||||||
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):
|
||||||
self.permission_denied(request)
|
self.permission_denied(
|
||||||
|
request, message=getattr(permission, 'message', None)
|
||||||
|
)
|
||||||
|
|
||||||
def check_object_permissions(self, request, obj):
|
def check_object_permissions(self, request, obj):
|
||||||
"""
|
"""
|
||||||
|
@ -311,7 +313,9 @@ class APIView(View):
|
||||||
"""
|
"""
|
||||||
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):
|
||||||
self.permission_denied(request)
|
self.permission_denied(
|
||||||
|
request, message=getattr(permission, 'message', None)
|
||||||
|
)
|
||||||
|
|
||||||
def check_throttles(self, request):
|
def check_throttles(self, request):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -376,3 +376,89 @@ class ObjectPermissionsIntegrationTests(TestCase):
|
||||||
response = object_permissions_list_view(request)
|
response = object_permissions_list_view(request)
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertListEqual(response.data, [])
|
self.assertListEqual(response.data, [])
|
||||||
|
|
||||||
|
|
||||||
|
class BasicPerm(permissions.BasePermission):
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class BasicPermWithDetail(permissions.BasePermission):
|
||||||
|
message = 'Custom: You cannot access this resource'
|
||||||
|
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class BasicObjectPerm(permissions.BasePermission):
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class BasicObjectPermWithDetail(permissions.BasePermission):
|
||||||
|
message = 'Custom: You cannot access this resource'
|
||||||
|
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionInstanceView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
|
queryset = BasicModel.objects.all()
|
||||||
|
serializer_class = BasicSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class DeniedView(PermissionInstanceView):
|
||||||
|
permission_classes = (BasicPerm,)
|
||||||
|
|
||||||
|
|
||||||
|
class DeniedViewWithDetail(PermissionInstanceView):
|
||||||
|
permission_classes = (BasicPermWithDetail,)
|
||||||
|
|
||||||
|
|
||||||
|
class DeniedObjectView(PermissionInstanceView):
|
||||||
|
permission_classes = (BasicObjectPerm,)
|
||||||
|
|
||||||
|
|
||||||
|
class DeniedObjectViewWithDetail(PermissionInstanceView):
|
||||||
|
permission_classes = (BasicObjectPermWithDetail,)
|
||||||
|
|
||||||
|
denied_view = DeniedView.as_view()
|
||||||
|
|
||||||
|
denied_view_with_detail = DeniedViewWithDetail.as_view()
|
||||||
|
|
||||||
|
denied_object_view = DeniedObjectView.as_view()
|
||||||
|
|
||||||
|
denied_object_view_with_detail = DeniedObjectViewWithDetail.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
class CustomPermissionsTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
BasicModel(text='foo').save()
|
||||||
|
User.objects.create_user('username', 'username@example.com', 'password')
|
||||||
|
credentials = basic_auth_header('username', 'password')
|
||||||
|
self.request = factory.get('/1', format='json', HTTP_AUTHORIZATION=credentials)
|
||||||
|
self.custom_message = 'Custom: You cannot access this resource'
|
||||||
|
|
||||||
|
def test_permission_denied(self):
|
||||||
|
response = denied_view(self.request, pk=1)
|
||||||
|
detail = response.data.get('detail')
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||||
|
self.assertNotEqual(detail, self.custom_message)
|
||||||
|
|
||||||
|
def test_permission_denied_with_custom_detail(self):
|
||||||
|
response = denied_view_with_detail(self.request, pk=1)
|
||||||
|
detail = response.data.get('detail')
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||||
|
self.assertEqual(detail, self.custom_message)
|
||||||
|
|
||||||
|
def test_permission_denied_for_object(self):
|
||||||
|
response = denied_object_view(self.request, pk=1)
|
||||||
|
detail = response.data.get('detail')
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||||
|
self.assertNotEqual(detail, self.custom_message)
|
||||||
|
|
||||||
|
def test_permission_denied_for_object_with_custom_detail(self):
|
||||||
|
response = denied_object_view_with_detail(self.request, pk=1)
|
||||||
|
detail = response.data.get('detail')
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||||
|
self.assertEqual(detail, self.custom_message)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user