@@ -56,6 +56,26 @@ def permissions_allowed_for_system_role() -> dict[Type[Model], list[str]]:
5656    return  permissions_by_model 
5757
5858
59+ def  get_descendent_models_from_db (main_ct : Model ):
60+     """For a given content type, get all content types from the database that reference them as a parent 
61+ 
62+     Including any content types that reference a content type that reference this content type as a parent. 
63+     """ 
64+     seen_ids  =  set ()
65+     result  =  []
66+     queue  =  [main_ct ]
67+ 
68+     while  queue :
69+         current  =  queue .pop (0 )
70+         for  child  in  current .child_content_types .all ():
71+             if  child .pk  not  in   seen_ids :
72+                 seen_ids .add (child .pk )
73+                 result .append (child )
74+                 queue .append (child )
75+ 
76+     return  result 
77+ 
78+ 
5979def  permissions_allowed_for_role (cls ) ->  dict [Union [Type [Model ], Type [RemoteObject ]], list [str ]]:
6080    "Permission codenames valid for a RoleDefinition of given class, organized by permission class" 
6181    if  cls  is  None :
@@ -66,19 +86,21 @@ def permissions_allowed_for_role(cls) -> dict[Union[Type[Model], Type[RemoteObje
6686
6787    permissions_by_model  =  defaultdict (list )
6888
89+     # Warm cache to load all types and related permissions 
90+     permission_registry .content_type_model .objects .warm_cache (permission_registry .content_type_model .objects .prefetch_related ('dab_permissions' ))
91+ 
92+     # Add direct model permissions 
6993    cls_ct  =  permission_registry .content_type_model .objects .get_for_model (cls )
7094    for  permission  in  cls_ct .dab_permissions .all ():
7195        if  not  is_add_perm (permission .codename ):
7296            permissions_by_model [cls ].append (permission .codename )
7397
7498    # Add permissions for all child types 
75-     for  ct  in  cls_ct .child_content_types .prefetch_related ('dab_permissions' ):
76-         for  permission  in  ct .dab_permissions .prefetch_related ('content_type__child_content_types' ):
77-             permissions_by_model [ct .model_class ()].append (permission .codename )
78-             # Process grandchild models 
79-             for  grandchild_ct  in  permission .content_type .child_content_types .all ():
80-                 for  grandchild_perm  in  grandchild_ct .dab_permissions .all ():
81-                     permissions_by_model [grandchild_ct .model_class ()].append (grandchild_perm .codename )
99+     for  ct  in  get_descendent_models_from_db (cls_ct ):
100+         for  child_permission  in  ct .dab_permissions .all ():
101+             # Include add permissions for child models 
102+             permissions_by_model [ct .model_class ()].append (child_permission .codename )
103+ 
82104    return  permissions_by_model 
83105
84106
0 commit comments