From 4f10c4e43ee57f4a2e387e0c8d44d28d21a3621c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 21 Mar 2024 22:45:12 +0000 Subject: [PATCH] =?UTF-8?q?Revert=20"Fix=20Respect=20`can=5Fread=5Fmodel`?= =?UTF-8?q?=20permission=20in=20DjangoModelPermissions=20(#8=E2=80=A6"=20(?= =?UTF-8?q?#9332)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 0618fa88e1a8c2cf8a2aab29ef6de66b49e5f7ed. --- docs/api-guide/permissions.md | 3 +-- rest_framework/permissions.py | 11 +++-------- tests/test_permissions.py | 21 +-------------------- 3 files changed, 5 insertions(+), 30 deletions(-) diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 5e0b6a153..775888fb6 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -173,12 +173,11 @@ This permission is suitable if you want to your API to allow read permissions to This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth]. This permission must only be applied to views that have a `.queryset` property or `get_queryset()` method. Authorization will only be granted if the user *is authenticated* and has the *relevant model permissions* assigned. The appropriate model is determined by checking `get_queryset().model` or `queryset.model`. -* `GET` requests require the user to have the `view` or `change` permission on the model * `POST` requests require the user to have the `add` permission on the model. * `PUT` and `PATCH` requests require the user to have the `change` permission on the model. * `DELETE` requests require the user to have the `delete` permission on the model. -The default behaviour can also be overridden to support custom model permissions. +The default behavior can also be overridden to support custom model permissions. For example, you might want to include a `view` model permission for `GET` requests. To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details. diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 8fb4569cb..71de226f9 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -186,9 +186,9 @@ class DjangoModelPermissions(BasePermission): # Override this if you need to also provide 'view' permissions, # or if you want to provide custom permission codes. perms_map = { - 'GET': ['%(app_label)s.view_%(model_name)s'], + 'GET': [], 'OPTIONS': [], - 'HEAD': ['%(app_label)s.view_%(model_name)s'], + 'HEAD': [], 'POST': ['%(app_label)s.add_%(model_name)s'], 'PUT': ['%(app_label)s.change_%(model_name)s'], 'PATCH': ['%(app_label)s.change_%(model_name)s'], @@ -239,13 +239,8 @@ class DjangoModelPermissions(BasePermission): queryset = self._queryset(view) perms = self.get_required_permissions(request.method, queryset.model) - change_perm = self.get_required_permissions('PUT', queryset.model) - user = request.user - if request.method == 'GET': - return user.has_perms(perms) or user.has_perms(change_perm) - - return user.has_perms(perms) + return request.user.has_perms(perms) class DjangoModelPermissionsOrAnonReadOnly(DjangoModelPermissions): diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 428480dc7..aefff981e 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -80,8 +80,7 @@ class ModelPermissionsIntegrationTests(TestCase): user.user_permissions.set([ Permission.objects.get(codename='add_basicmodel'), Permission.objects.get(codename='change_basicmodel'), - Permission.objects.get(codename='delete_basicmodel'), - Permission.objects.get(codename='view_basicmodel') + Permission.objects.get(codename='delete_basicmodel') ]) user = User.objects.create_user('updateonly', 'updateonly@example.com', 'password') @@ -140,15 +139,6 @@ class ModelPermissionsIntegrationTests(TestCase): response = get_queryset_list_view(request, pk=1) self.assertEqual(response.status_code, status.HTTP_201_CREATED) - def test_has_get_permissions(self): - request = factory.get('/', HTTP_AUTHORIZATION=self.permitted_credentials) - response = root_view(request) - self.assertEqual(response.status_code, status.HTTP_200_OK) - - request = factory.get('/1', HTTP_AUTHORIZATION=self.updateonly_credentials) - response = root_view(request, pk=1) - self.assertEqual(response.status_code, status.HTTP_200_OK) - def test_has_put_permissions(self): request = factory.put('/1', {'text': 'foobar'}, format='json', HTTP_AUTHORIZATION=self.permitted_credentials) @@ -166,15 +156,6 @@ class ModelPermissionsIntegrationTests(TestCase): response = root_view(request, pk=1) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_does_not_have_get_permissions(self): - request = factory.get('/', HTTP_AUTHORIZATION=self.disallowed_credentials) - response = root_view(request) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - - request = factory.get('/1', HTTP_AUTHORIZATION=self.disallowed_credentials) - response = root_view(request, pk=1) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_does_not_have_put_permissions(self): request = factory.put('/1', {'text': 'foobar'}, format='json', HTTP_AUTHORIZATION=self.disallowed_credentials)