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