1
1
from __future__ import unicode_literals
2
- from django .contrib .auth .models import User , Permission
2
+ from django .contrib .auth .models import User , Permission , Group
3
3
from django .db import models
4
4
from django .test import TestCase
5
5
from rest_framework import generics , status , permissions , authentication , HTTP_HEADER_ENCODING
6
+ from rest_framework .compat import guardian
7
+ from rest_framework .filters import ObjectPermissionReaderFilter
6
8
from rest_framework .test import APIRequestFactory
9
+ from rest_framework .tests .models import BasicModel
7
10
import base64
8
11
9
12
factory = APIRequestFactory ()
10
13
11
-
12
- class BasicModel (models .Model ):
13
- text = models .CharField (max_length = 100 )
14
-
15
-
16
14
class RootView (generics .ListCreateAPIView ):
17
15
model = BasicModel
18
16
authentication_classes = [authentication .BasicAuthentication ]
@@ -144,45 +142,136 @@ def test_options_updateonly(self):
144
142
self .assertEqual (list (response .data ['actions' ].keys ()), ['PUT' ])
145
143
146
144
147
- class OwnerModel (models .Model ):
145
+ class BasicPermModel (models .Model ):
148
146
text = models .CharField (max_length = 100 )
149
- owner = models .ForeignKey (User )
150
-
151
147
152
- class IsOwnerPermission (permissions .BasePermission ):
153
- def has_object_permission (self , request , view , obj ):
154
- return request .user == obj .owner
148
+ class Meta :
149
+ app_label = 'tests'
150
+ permissions = (
151
+ ('read_basicpermmodel' , 'Can view basic perm model' ),
152
+ # add, change, delete built in to django
153
+ )
155
154
156
-
157
- class OwnerInstanceView (generics .RetrieveUpdateDestroyAPIView ):
158
- model = OwnerModel
155
+ class ObjectPermissionInstanceView (generics .RetrieveUpdateDestroyAPIView ):
156
+ model = BasicPermModel
159
157
authentication_classes = [authentication .BasicAuthentication ]
160
- permission_classes = [IsOwnerPermission ]
161
-
162
-
163
- owner_instance_view = OwnerInstanceView .as_view ()
164
-
158
+
F438
permission_classes = [permissions .DjangoObjectLevelModelPermissions ]
165
159
166
- class ObjectPermissionsIntegrationTests (TestCase ):
167
- """
168
- Integration tests for the object level permissions API.
169
- """
160
+ object_permissions_view = ObjectPermissionInstanceView .as_view ()
170
161
171
- def setUp (self ):
172
- User .objects .create_user ('not_owner' , 'not_owner@example.com' , 'password' )
173
- user = User .objects .create_user ('owner' , 'owner@example.com' , 'password' )
174
-
175
- self .not_owner_credentials = basic_auth_header ('not_owner' , 'password' )
176
- self .owner_credentials = basic_auth_header ('owner' , 'password' )
177
-
178
- OwnerModel (text = 'foo' , owner = user ).save ()
179
-
180
- def test_owner_has_delete_permissions (self ):
181
- request = factory .delete ('/1' , HTTP_AUTHORIZATION = self .owner_credentials )
182
- response = owner_instance_view (request , pk = '1' )
183
- self .assertEqual (response .status_code , status .HTTP_204_NO_CONTENT )
184
-
185
- def test_non_owner_does_not_have_delete_permissions (self ):
186
- request = factory .delete ('/1' , HTTP_AUTHORIZATION = self .not_owner_credentials )
187
- response = owner_instance_view (request , pk = '1' )
188
- self .assertEqual (response .status_code , status .HTTP_403_FORBIDDEN )
162
+ class ObjectPermissionListView (generics .ListAPIView ):
163
+ model = BasicPermModel
164
+ authentication_classes = [authentication .BasicAuthentication ]
165
+ permission_classes = [permissions .DjangoObjectLevelModelPermissions ]
166
+
167
+ object_permissions_list_view = ObjectPermissionListView .as_view ()
168
+
169
+ if guardian :
170
+ from guardian .shortcuts import assign_perm
171
+
172
+ class ObjectPermissionsIntegrationTests (TestCase ):
173
+ """
174
+ Integration tests for the object level permissions API.
175
+ """
176
+ @classmethod
177
+ def setUpClass (cls ):
178
+ # create users
179
+ create = User .objects .create_user
180
+ users = {
181
+ 'fullaccess' : create ('fullaccess' , 'fullaccess@example.com' , 'password' ),
182
+ 'readonly' : create ('readonly' , 'readonly@example.com' , 'password' ),
183
+ 'writeonly' : create ('writeonly' , 'writeonly@example.com' , 'password' ),
184
+ 'deleteonly' : create ('deleteonly' , 'deleteonly@example.com' , 'password' ),
185
+ }
186
+
187
+ # give everyone model level permissions, as we are not testing those
188
+ everyone = Group .objects .create (name = 'everyone' )
189
+ model_name = BasicPermModel ._meta .module_name
190
+ app_label = BasicPermModel ._meta .app_label
191
+ f = '{0}_{1}' .format
192
+ perms = {
193
+ 'read' : f ('read' , model_name ),
194
+ 'change' : f ('change' , model_name ),
195
+ 'delete' : f ('delete' , model_name )
196
+ }
197
+ for perm in perms .values ():
198
+ perm = '{0}.{1}' .format (app_label , perm )
199
+ assign_perm (perm , everyone )
200
+ everyone .user_set .add (* users .values ())
201
+
202
+ cls .perms = perms
203
+ cls .users = users
204
+
205
+ def setUp (self ):
206
+ perms = self .perms
207
+ users = self .users
208
+
209
+ # appropriate object level permissions
210
+ readers = Group .objects .create (name = 'readers' )
211
+ writers = Group .objects .create (name = 'writers' )
212
+ deleters = Group .objects .create (name = 'deleters' )
213
+
214
+ model = BasicPermModel .objects .create (text = 'foo' )
215
+
216
+ assign_perm (perms ['read' ], readers , model )
217
+ assign_perm (perms ['change' ], writers , model )
218
+ assign_perm (perms ['delete' ], deleters , model )
219
+
220
+ readers .user_set .add (users ['fullaccess' ], users ['readonly' ])
221
+ writers .user_set .add (users ['fullaccess' ], users ['writeonly' ])
222
+ deleters .user_set .add (users ['fullaccess' ], users ['deleteonly' ])
223
+
224
+ self .credentials = {}
225
+ for user in users .values ():
226
+ self .credentials [user .username ] = basic_auth_header (user .username , 'password' )
227
+
228
+ # Delete
229
+ def test_can_delete_permissions (self ):
230
+ request = factory .delete ('/1' , HTTP_AUTHORIZATION = self .credentials ['deleteonly' ])
231
+ response = object_permissions_view (request , pk = '1' )
232
+ self .assertEqual (response .status_code , status .HTTP_204_NO_CONTENT )
233
+
234
+ def test_cannot_delete_permissions (self ):
235
+ request = factory .delete ('/1' , HTTP_AUTHORIZATION = self .credentials ['readonly' ])
236
+ response = object_permissions_view (request , pk = '1' )
237
+ self .assertEqual (response .status_code , status .HTTP_404_NOT_FOUND )
238
+
239
+ # Update
240
+ def test_can_update_permissions (self ):
241
+ request = factory .patch ('/1' , {'text' : 'foobar' }, format = 'json' ,
242
+ HTTP_AUTHORIZATION = self .credentials ['writeonly' ])
243
+ response = object_permissions_view (request , pk = '1' )
244
+ self .assertEqual (response .status_code , status .HTTP_200_OK )
245
+ self .assertEqual (response .data .get ('text' ), 'foobar' )
246
+
247
+ def test_cannot_update_permissions (self ):
248
+ request = factory .patch ('/1' , {'text' : 'foobar' }, format = 'json' ,
249
+ HTTP_AUTHORIZATION = self .credentials ['deleteonly' ])
250
+ response = object_permissions_view (request , pk = '1' )
251
+ self .assertEqual (response .status_code , status .HTTP_404_NOT_FOUND )
252
+
253
+ # Read
254
+ def test_can_read_permissions (self ):
255
+ request = factory .get ('/1' , HTTP_AUTHORIZATION = self .credentials ['readonly' ])
256
+ response = object_permissions_view (request , pk = '1' )
257
+ self .assertEqual (response .status_code , status .HTTP_200_OK )
258
+
259
+ def test_cannot_read_permissions (self ):
260
+ request = factory .get ('/1' , HTTP_AUTHORIZATION = self .credentials ['writeonly' ])
261
+ response = object_permissions_view (request , pk = '1' )
262
+ self .assertEqual (response .status_code , status .HTTP_404_NOT_FOUND )
263
+
264
+ # Read list
265
+ def test_can_read_list_permissions (self ):
266
+ request = factory .get ('/' , HTTP_AUTHORIZATION = self .credentials ['readonly' ])
267
+ object_permissions_list_view .cls .filter_backends = (ObjectPermissionReaderFilter ,)
268
+ response = object_permissions_list_view (request )
269
+ self .assertEqual (response .status_code , status .HTTP_200_OK )
270
+ self .assertEqual (response .data [0 ].get ('id' ), 1 )
271
+
272
+ def test_cannot_read_list_permissions (self ):
273
+ request = factory .get ('/' , HTTP_AUTHORIZATION = self .credentials ['writeonly' ])
274
+ object_permissions_list_view .cls .filter_backends = (ObjectPermissionReaderFilter ,)
275
+ response = object_permissions_list_view (request )
276
+ self .assertEqual (response .status_code , status .HTTP_200_OK )
277
+ self .assertListEqual (response .data , [])
0 commit comments