2020 RoleMetadataSerializer ,
2121 RoleTeamAssignmentSerializer ,
2222 RoleUserAssignmentSerializer ,
23+ TeamAccessAssignmentSerializer ,
2324 TeamAccessListMixin ,
25+ UserAccessAssignmentSerializer ,
2426 UserAccessListMixin ,
2527)
2628from ansible_base .rbac .evaluations import has_super_permission
3436from ..policies import check_content_obj_permission
3537from ..remote import RemoteObject , get_resource_prefix
3638from ..sync import maybe_reverse_sync_assignment , maybe_reverse_sync_unassignment
39+ from .queries import assignment_qs_user_to_obj , assignment_qs_user_to_obj_perm
3740
3841
3942def list_combine_values (data : dict [Type [Model ], list [str ]]) -> list [str ]:
@@ -220,7 +223,61 @@ class RoleUserAssignmentViewSet(BaseAssignmentViewSet):
220223 ]
221224
222225
226+ class AccessURLMixin :
227+ def get_actor_model (self ):
228+ return get_user_model ()
229+
230+ def get_url_permission (self ):
231+ model_name = self .kwargs .get ("model_name" )
232+ # Prefer treating the URL as requesting for some permission
233+ return DABPermission .objects .filter (api_slug = model_name ).first ()
234+
235+ def get_url_content_type (self ):
236+ if getattr (self , 'permission' , None ):
237+ # Access list will be all permissions for the given object
238+ return self .permission .content_type
239+
240+ model_name = self .kwargs .get ("model_name" )
241+ content_type = DABContentType .objects .filter (api_slug = model_name ).first ()
242+ if not content_type :
243+ raise NotFound (f'The slug { model_name } is not a valid permission or type identifier' )
244+
245+ return content_type
246+
247+ def get_url_obj (self ):
248+ model_cls = self .content_type .model_class ()
249+ object_id = self .kwargs .get ("pk" )
250+ if not issubclass (model_cls , RemoteObject ):
251+ try :
252+ return model_cls .objects .get (pk = object_id )
253+ except model_cls .DoesNotExist :
254+ raise NotFound (f'The primary key { object_id } was not found for model { model_cls } ' )
255+ else :
256+ return model_cls (content_type = self .content_type , object_id = object_id )
257+
258+ def check_permission_to_object (self , obj ):
259+ try :
260+ if not self .request .user .has_obj_perm (obj , 'view' ):
261+ raise NotFound
262+ except RuntimeError :
263+ check_content_obj_permission (self .request .user , obj )
264+
265+ def get_serializer_context (self ):
266+ ctx = super ().get_serializer_context ()
267+ self .get_data_from_url ()
268+
269+ ctx .update (
270+ {
271+ "permission" : self .permission ,
272+ "related_object" : self .related_object ,
273+ "content_type" : self .content_type ,
274+ }
275+ )
276+ return ctx
277+
278+
223279class UserAccessViewSet (
280+ AccessURLMixin ,
224281 AnsibleBaseDjangoAppApiView ,
225282 mixins .ListModelMixin ,
226283 GenericViewSet ,
@@ -232,40 +289,12 @@ class UserAccessViewSet(
232289
233290 serializer_mixin = UserAccessListMixin
234291
235- def get_actor_model (self ):
236- return get_user_model ()
237-
238292 def get_data_from_url (self ):
239293 if not hasattr (self , 'related_object' ):
240- model_name = self .kwargs .get ("model_name" )
241- object_id = self .kwargs .get ("pk" )
242-
243- # Prefer treating the URL as requesting for some permission
244- self .permission = DABPermission .objects .filter (api_slug = model_name ).first ()
245-
246- if not self .permission :
247- self .content_type = DABContentType .objects .filter (api_slug = model_name ).first ()
248- if not self .content_type :
249- raise NotFound (f'The slug { model_name } is not a valid permission or type identifier' )
250- else :
251- # Access list will be all permissions for the given object
252- self .content_type = self .permission .content_type
253-
254- model_cls = self .content_type .model_class ()
255- if not issubclass (model_cls , RemoteObject ):
256- try :
257- self .related_object = model_cls .objects .get (pk = object_id )
258- except model_cls .DoesNotExist :
259- raise NotFound
260- else :
261- self .related_object = model_cls (content_type = self .content_type , object_id = object_id )
262-
263- try :
264- if not self .request .user .has_obj_perm (self .related_object , 'view' ):
265- raise NotFound
266- except RuntimeError :
267- check_content_obj_permission (self .request .user , self .related_object )
268-
294+ self .permission = self .get_url_permission ()
295+ self .content_type = self .get_url_content_type ()
296+ self .related_object = self .get_url_obj ()
297+ self .check_permission_to_object (self .related_object )
269298 return (self .permission , self .content_type , self .related_object )
270299
271300 def get_queryset (self ):
@@ -315,22 +344,55 @@ class Meta:
315344
316345 return DynamicActorSerializer
317346
318- def get_serializer_context (self ):
319- ctx = super ().get_serializer_context ()
320- permission , ct , obj = self .get_data_from_url ()
321-
322- ctx .update (
323- {
324- "permission" : permission ,
325- "related_object" : obj ,
326- "content_type" : ct ,
327- }
328- )
329- return ctx
330-
331347
332348class TeamAccessViewSet (UserAccessViewSet ):
333349 serializer_mixin = TeamAccessListMixin
334350
335351 def get_actor_model (self ):
336352 return get_team_model ()
353+
354+
355+ class UserAccessAssignmentViewSet (
356+ AccessURLMixin ,
357+ AnsibleBaseDjangoAppApiView ,
358+ mixins .ListModelMixin ,
359+ GenericViewSet ,
360+ ):
361+ """
362+ This gives drill-down information about the means of inheritance
363+ for all the permissions show in the higher-level view of the access list
364+ """
365+
366+ serializer_class = UserAccessAssignmentSerializer
367+
368+ def get_url_actor (self ):
369+ actor_pk = self .kwargs .get ("actor_pk" )
370+ actor_cls = self .get_actor_model ()
371+ try :
372+ return actor_cls .objects .get (pk = actor_pk )
373+ except actor_cls .DoesNotExist :
374+ raise NotFound (f'The { actor_cls ._meta .model_name } with pk={ actor_pk } can not be found' )
375+
376+ def get_data_from_url (self ):
377+ if not hasattr (self , 'related_object' ):
378+ self .permission = self .get_url_permission ()
379+ self .content_type = self .get_url_content_type ()
380+ self .related_object = self .get_url_obj ()
381+ self .actor = self .get_url_actor ()
382+ self .check_permission_to_object (self .related_object )
383+ return (self .permission , self .content_type , self .related_object , self .actor )
384+
385+ def get_queryset (self ):
386+ permission , ct , obj , actor = self .get_data_from_url ()
387+
388+ if permission :
389+ return assignment_qs_user_to_obj_perm (actor , obj , permission )
390+ else :
391+ return assignment_qs_user_to_obj (actor , obj )
392+
393+
394+ class TeamAccessAssignmentViewSet (UserAccessAssignmentViewSet ):
395+ serializer_class = TeamAccessAssignmentSerializer
396+
397+ def get_actor_model (self ):
398+ return get_team_model ()
0 commit comments