Skip to content

Commit 58dcb56

Browse files
committed
Light refactor to more inner part of recomputation
1 parent 2fe15ca commit 58dcb56

File tree

1 file changed

+44
-32
lines changed

1 file changed

+44
-32
lines changed

ansible_base/rbac/models/role.py

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,45 @@ def descendent_roles(self):
548548
descendents.update(set(target_team.has_roles.all()))
549549
return descendents
550550

551+
def get_child_filters(self, permission, role_content_type, types_prefetch):
552+
"Given a permission that a certain object role grants, returns child object filter instructions"
553+
filter_path = None
554+
child_model = None
555+
role_model = role_content_type.model_class()
556+
permission_content_type = types_prefetch.get_content_type(permission.content_type_id)
557+
permission_model = permission_content_type.model_class()
558+
if is_add_perm(permission.codename):
559+
# Add evaluations for add permission to children which are parents of the permission model
560+
# this only matters when for multi-layer inheritance (grandchildren)
561+
if issubclass(permission_model, RemoteObject):
562+
eval_ct = permission_content_type.parent_content_type
563+
if eval_ct == role_content_type:
564+
return (None, None, None) # this permission is for a direct child model
565+
else:
566+
for path, model in permission_registry.get_child_models(role_model):
567+
if '__' in path and model._meta.model_name == permission_content_type.model:
568+
path_to_parent, filter_path = path.split('__', 1)
569+
child_model = permission_model._meta.get_field(path_to_parent).related_model
570+
eval_ct = DABContentType.objects.get_for_model(child_model).id
571+
break
572+
if not child_model:
573+
return (None, None, None) # this permission is for a direct child model
574+
elif issubclass(permission_model, RemoteObject):
575+
eval_ct = permission.content_type_id
576+
else:
577+
for path, model in permission_registry.get_child_models(role_model):
578+
if model._meta.model_name == permission_content_type.model:
579+
filter_path = path
580+
child_model = model
581+
eval_ct = permission.content_type_id
582+
break
583+
else:
584+
logger.warning(f'{self.role_definition} listed {permission.codename} but model is not a child, ignoring')
585+
return (None, None, None)
586+
587+
return (eval_ct, child_model, filter_path)
588+
589+
551590
def expected_direct_permissions(self, types_prefetch=None) -> set[tuple[str, int, Union[int, UUID]]]:
552591
"""The expected permissions that holding this ObjectRole confers to the holder
553592
@@ -569,8 +608,6 @@ def expected_direct_permissions(self, types_prefetch=None) -> set[tuple[str, int
569608
# ObjectRole.object_id is stored as text, we convert it to the model pk native type
570609
object_id = role_model._meta.pk.to_python(self.object_id)
571610
for permission in types_prefetch.permissions_for_object_role(self):
572-
permission_content_type = types_prefetch.get_content_type(permission.content_type_id)
573-
permission_model = permission_content_type.model_class()
574611

575612
# direct object permission
576613
if permission.content_type_id == self.content_type_id:
@@ -582,43 +619,18 @@ def expected_direct_permissions(self, types_prefetch=None) -> set[tuple[str, int
582619
expected_evaluations.add((permission.codename, self.content_type_id, object_id))
583620

584621
# Add evaluations for child objects, where this role gives permission to child objects
585-
filter_path = None
586-
child_model = None
587-
if is_add_perm(permission.codename):
588-
# Add evaluations for add permission to children which are parents of the permission model
589-
# this only matters when for multi-layer inheritance (grandchildren)
590-
if issubclass(permission_model, RemoteObject):
591-
eval_ct = permission_content_type.parent_content_type
592-
if eval_ct == role_content_type:
593-
continue # this permission is for a direct child model
594-
else:
595-
for path, model in permission_registry.get_child_models(role_model):
596-
if '__' in path and model._meta.model_name == permission_content_type.model:
597-
path_to_parent, filter_path = path.split('__', 1)
598-
child_model = permission_model._meta.get_field(path_to_parent).related_model
599-
eval_ct = DABContentType.objects.get_for_model(child_model).id
600-
break
601-
if not child_model:
602-
continue # this permission is for a direct child model
603-
elif issubclass(permission_model, RemoteObject):
604-
eval_ct = permission.content_type_id
605-
else:
606-
for path, model in permission_registry.get_child_models(role_model):
607-
if model._meta.model_name == permission_content_type.model:
608-
filter_path = path
609-
child_model = model
610-
eval_ct = permission.content_type_id
611-
break
612-
else:
613-
logger.warning(f'{self.role_definition} listed {permission.codename} but model is not a child, ignoring')
614-
continue
622+
eval_ct, child_model, filter_path = self.get_child_filters(permission, role_content_type, types_prefetch)
623+
if not eval_ct:
624+
continue
615625

616626
# fetching child objects of an organization is very performance sensitive
617627
# for multiple permissions of same type, make sure to only do query once
618628
id_list = []
619629
if eval_ct in cached_id_lists:
620630
id_list = cached_id_lists[eval_ct]
621631
else:
632+
permission_content_type = types_prefetch.get_content_type(permission.content_type_id)
633+
permission_model = permission_content_type.model_class()
622634
if issubclass(permission_model, RemoteObject):
623635
# Build id_list from ObjectRole objects if it is remote object
624636
id_list = (

0 commit comments

Comments
 (0)