@@ -219,58 +219,17 @@ def get_me(self, request):
219
219
class ResourceAccessViewsetMixin :
220
220
"""Mixin with methods common to all access viewsets."""
221
221
222
- def get_permissions (self ):
223
- """User only needs to be authenticated to list resource accesses"""
224
- if self .action == "list" :
225
- permission_classes = [permissions .IsAuthenticated ]
226
- else :
227
- return super ().get_permissions ()
228
-
229
- return [permission () for permission in permission_classes ]
222
+ def filter_queryset (self , queryset ):
223
+ """Override to filter on related resource."""
224
+ queryset = super ().filter_queryset (queryset )
225
+ return queryset .filter (** {self .resource_field_name : self .kwargs ["resource_id" ]})
230
226
231
227
def get_serializer_context (self ):
232
228
"""Extra context provided to the serializer class."""
233
229
context = super ().get_serializer_context ()
234
230
context ["resource_id" ] = self .kwargs ["resource_id" ]
235
231
return context
236
232
237
- def get_queryset (self ):
238
- """Return the queryset according to the action."""
239
- queryset = super ().get_queryset ()
240
- queryset = queryset .filter (
241
- ** {self .resource_field_name : self .kwargs ["resource_id" ]}
242
- )
243
-
244
- if self .action == "list" :
245
- user = self .request .user
246
- teams = user .teams
247
- user_roles_query = (
248
- queryset .filter (
249
- db .Q (user = user ) | db .Q (team__in = teams ),
250
- ** {self .resource_field_name : self .kwargs ["resource_id" ]},
251
- )
252
- .values (self .resource_field_name )
253
- .annotate (roles_array = ArrayAgg ("role" ))
254
- .values ("roles_array" )
255
- )
256
-
257
- # Limit to resource access instances related to a resource THAT also has
258
- # a resource access
259
- # instance for the logged-in user (we don't want to list only the resource
260
- # access instances pointing to the logged-in user)
261
- queryset = (
262
- queryset .filter (
263
- db .Q (** {f"{ self .resource_field_name } __accesses__user" : user })
264
- | db .Q (
265
- ** {f"{ self .resource_field_name } __accesses__team__in" : teams }
266
- ),
267
- ** {self .resource_field_name : self .kwargs ["resource_id" ]},
268
- )
269
- .annotate (user_roles = db .Subquery (user_roles_query ))
270
- .distinct ()
271
- )
272
- return queryset
273
-
274
233
def destroy (self , request , * args , ** kwargs ):
275
234
"""Forbid deleting the last owner access"""
276
235
instance = self .get_object ()
@@ -1373,7 +1332,11 @@ def cors_proxy(self, request, *args, **kwargs):
1373
1332
1374
1333
class DocumentAccessViewSet (
1375
1334
ResourceAccessViewsetMixin ,
1376
- viewsets .ModelViewSet ,
1335
+ drf .mixins .CreateModelMixin ,
1336
+ drf .mixins .RetrieveModelMixin ,
1337
+ drf .mixins .UpdateModelMixin ,
1338
+ drf .mixins .DestroyModelMixin ,
1339
+ viewsets .GenericViewSet ,
1377
1340
):
1378
1341
"""
1379
1342
API ViewSet for all interactions with document accesses.
@@ -1400,31 +1363,35 @@ class DocumentAccessViewSet(
1400
1363
"""
1401
1364
1402
1365
lookup_field = "pk"
1403
- pagination_class = Pagination
1404
1366
permission_classes = [permissions .IsAuthenticated , permissions .AccessPermission ]
1405
1367
queryset = models .DocumentAccess .objects .select_related ("user" ).all ()
1406
1368
resource_field_name = "document"
1407
1369
serializer_class = serializers .DocumentAccessSerializer
1408
1370
is_current_user_owner_or_admin = False
1409
1371
1410
- def get_queryset (self ):
1411
- """Return the queryset according to the action."""
1412
- queryset = super ().get_queryset ()
1372
+ def list (self , request , * args , ** kwargs ):
1373
+ """Return accesses for the current document with filters and annotations."""
1374
+ user = self .request .user
1375
+ queryset = self .filter_queryset (self .get_queryset ())
1413
1376
1414
- if self .action == "list" :
1415
- try :
1416
- document = models .Document .objects .get (pk = self .kwargs ["resource_id" ])
1417
- except models .Document .DoesNotExist :
1418
- return queryset .none ()
1377
+ try :
1378
+ document = models .Document .objects .get (pk = self .kwargs ["resource_id" ])
1379
+ except models .Document .DoesNotExist :
1380
+ return drf .response .Response ([])
1419
1381
1420
- roles = set (document .get_roles (self .request .user ))
1421
- is_owner_or_admin = bool (roles .intersection (set (models .PRIVILEGED_ROLES )))
1422
- self .is_current_user_owner_or_admin = is_owner_or_admin
1423
- if not is_owner_or_admin :
1424
- # Return only the document owner access
1425
- queryset = queryset .filter (role__in = models .PRIVILEGED_ROLES )
1382
+ roles = set (document .get_roles (user ))
1383
+ if not roles :
1384
+ return drf .response .Response ([])
1426
1385
1427
- return queryset
1386
+ is_owner_or_admin = bool (roles .intersection (set (models .PRIVILEGED_ROLES )))
1387
+ self .is_current_user_owner_or_admin = is_owner_or_admin
1388
+ if not is_owner_or_admin :
1389
+ # Return only the document's privileged accesses
1390
+ queryset = queryset .filter (role__in = models .PRIVILEGED_ROLES )
1391
+
1392
+ queryset = queryset .distinct ()
1393
+ serializer = self .get_serializer (queryset , many = True )
1394
+ return drf .response .Response (serializer .data )
1428
1395
1429
1396
def get_serializer_class (self ):
1430
1397
if self .action == "list" and not self .is_current_user_owner_or_admin :
@@ -1542,7 +1509,6 @@ class TemplateAccessViewSet(
1542
1509
ResourceAccessViewsetMixin ,
1543
1510
drf .mixins .CreateModelMixin ,
1544
1511
drf .mixins .DestroyModelMixin ,
1545
- drf .mixins .ListModelMixin ,
1546
1512
drf .mixins .RetrieveModelMixin ,
1547
1513
drf .mixins .UpdateModelMixin ,
1548
1514
viewsets .GenericViewSet ,
@@ -1572,12 +1538,28 @@ class TemplateAccessViewSet(
1572
1538
"""
1573
1539
1574
1540
lookup_field = "pk"
1575
- pagination_class = Pagination
1576
1541
permission_classes = [permissions .IsAuthenticated , permissions .AccessPermission ]
1577
1542
queryset = models .TemplateAccess .objects .select_related ("user" ).all ()
1578
1543
resource_field_name = "template"
1579
1544
serializer_class = serializers .TemplateAccessSerializer
1580
1545
1546
+ def list (self , request , * args , ** kwargs ):
1547
+ """Restrict templates returned by the list endpoint"""
1548
+ user = self .request .user
1549
+ teams = user .teams
1550
+ queryset = self .filter_queryset (self .get_queryset ())
1551
+
1552
+ # Limit to resource access instances related to a resource THAT also has
1553
+ # a resource access instance for the logged-in user (we don't want to list
1554
+ # only the resource access instances pointing to the logged-in user)
1555
+ queryset = queryset .filter (
1556
+ db .Q (template__accesses__user = user )
1557
+ | db .Q (template__accesses__team__in = teams ),
1558
+ ).distinct ()
1559
+
1560
+ serializer = self .get_serializer (queryset , many = True )
1561
+ return drf .response .Response (serializer .data )
1562
+
1581
1563
1582
1564
class InvitationViewset (
1583
1565
drf .mixins .CreateModelMixin ,
0 commit comments