From c0d95cb9678b1693f8f1a8658d4665c51de87ddf Mon Sep 17 00:00:00 2001 From: Denny Biasiolli Date: Tue, 22 Nov 2022 15:21:16 +0100 Subject: [PATCH] Fix #8771 - Checking for authentication even if `_ignore_model_permissions = True` (#8772) --- rest_framework/permissions.py | 8 ++++---- tests/test_permissions.py | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index f3ebbcffa..71de226f9 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -228,15 +228,15 @@ class DjangoModelPermissions(BasePermission): return view.queryset def has_permission(self, request, view): + if not request.user or ( + not request.user.is_authenticated and self.authenticated_users_only): + return False + # Workaround to ensure DjangoModelPermissions are not applied # to the root view when using DefaultRouter. if getattr(view, '_ignore_model_permissions', False): return True - if not request.user or ( - not request.user.is_authenticated and self.authenticated_users_only): - return False - queryset = self._queryset(view) perms = self.get_required_permissions(request.method, queryset.model) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index f00b57ec1..aefff981e 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -55,11 +55,16 @@ class EmptyListView(generics.ListCreateAPIView): permission_classes = [permissions.DjangoModelPermissions] +class IgnoredGetQuerySetListView(GetQuerySetListView): + _ignore_model_permissions = True + + root_view = RootView.as_view() api_root_view = DefaultRouter().get_api_root_view() instance_view = InstanceView.as_view() get_queryset_list_view = GetQuerySetListView.as_view() empty_list_view = EmptyListView.as_view() +ignored_get_queryset_list_view = IgnoredGetQuerySetListView.as_view() def basic_auth_header(username, password): @@ -107,6 +112,27 @@ class ModelPermissionsIntegrationTests(TestCase): response = api_root_view(request) self.assertEqual(response.status_code, status.HTTP_200_OK) + def test_ignore_model_permissions_with_unauthenticated_user(self): + """ + We check that the ``_ignore_model_permissions`` attribute + doesn't ignore the authentication. + """ + request = factory.get('/', format='json') + request.resolver_match = ResolverMatch('get', (), {}) + response = ignored_get_queryset_list_view(request) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_ignore_model_permissions_with_authenticated_user(self): + """ + We check that the ``_ignore_model_permissions`` attribute + with an authenticated user. + """ + request = factory.get('/', format='json', + HTTP_AUTHORIZATION=self.permitted_credentials) + request.resolver_match = ResolverMatch('get', (), {}) + response = ignored_get_queryset_list_view(request) + self.assertEqual(response.status_code, status.HTTP_200_OK) + def test_get_queryset_has_create_permissions(self): request = factory.post('/', {'text': 'foobar'}, format='json', HTTP_AUTHORIZATION=self.permitted_credentials)