Skip to content

Commit 8bd001d

Browse files
committed
Respect can_read_model in DjangoModelPermissions
Django version 2.1 introduced the `can_read_model` permission to support read-only ModelAdmin views. Add support for this permission to a DjangoModelPermissions subclass. (A subclass is created in order to preserve backwards-compatibility with versions of Django that don't support this flag).
1 parent 2084555 commit 8bd001d

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

rest_framework/permissions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class DjangoModelPermissions(BasePermission):
151151
# Override this if you need to also provide 'view' permissions,
152152
# or if you want to provide custom permission codes.
153153
perms_map = {
154-
'GET': [],
154+
'GET': ['%(app_label)s.view_%(model_name)s'],
155155
'OPTIONS': [],
156156
'HEAD': [],
157157
'POST': ['%(app_label)s.add_%(model_name)s'],

tests/test_permissions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,15 @@ def setUp(self):
8787
Permission.objects.get(codename='change_basicmodel'),
8888
])
8989

90+
user = User.objects.create_user('readonly', '[email protected]', 'password')
91+
user.user_permissions.set([
92+
Permission.objects.get(codename='view_basicmodel'),
93+
])
94+
9095
self.permitted_credentials = basic_auth_header('permitted', 'password')
9196
self.disallowed_credentials = basic_auth_header('disallowed', 'password')
9297
self.updateonly_credentials = basic_auth_header('updateonly', 'password')
98+
self.readonly_credentials = basic_auth_header('readonly', 'password')
9399

94100
BasicModel(text='foo').save()
95101

@@ -117,6 +123,12 @@ def test_get_queryset_has_create_permissions(self):
117123
response = get_queryset_list_view(request, pk=1)
118124
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
119125

126+
def test_has_read_permissions(self):
127+
request = factory.get('/', {'text': 'foobar'}, format='json',
128+
HTTP_AUTHORIZATION=self.permitted_credentials)
129+
response = root_view(request, pk=1)
130+
self.assertEqual(response.status_code, status.HTTP_200_OK)
131+
120132
def test_has_put_permissions(self):
121133
request = factory.put('/1', {'text': 'foobar'}, format='json',
122134
HTTP_AUTHORIZATION=self.permitted_credentials)
@@ -134,6 +146,12 @@ def test_does_not_have_create_permissions(self):
134146
response = root_view(request, pk=1)
135147
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
136148

149+
def test_does_not_have_read_permissions(self):
150+
request = factory.get('/', {'text': 'foobar'}, format='json',
151+
HTTP_AUTHORIZATION=self.disallowed_credentials)
152+
response = root_view(request, pk=1)
153+
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
154+
137155
def test_does_not_have_put_permissions(self):
138156
request = factory.put('/1', {'text': 'foobar'}, format='json',
139157
HTTP_AUTHORIZATION=self.disallowed_credentials)

0 commit comments

Comments
 (0)