From d05b0a5379f56e74ba59fa142872fe59a9b068d7 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Thu, 20 Jun 2024 15:26:28 -0400 Subject: [PATCH] Allow role assignment queries to use .only --- ansible_base/rbac/models.py | 14 +++++++++----- .../tests/rbac/models/test_role_assignments.py | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 test_app/tests/rbac/models/test_role_assignments.py diff --git a/ansible_base/rbac/models.py b/ansible_base/rbac/models.py index 12a1be4cd..54526cfa0 100644 --- a/ansible_base/rbac/models.py +++ b/ansible_base/rbac/models.py @@ -389,11 +389,15 @@ class Meta: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Cache fields from the associated object_role - if self.object_role_id and not self.object_id: - self.object_id = self.object_role.object_id - self.content_type_id = self.object_role.content_type_id - self.role_definition_id = self.object_role.role_definition_id + # Fields from object_role are cached onto assignment objects, only when creating new assignments + # we must be very careful to avoid referencing deferred attributes to avoid RecursionError + def_fields = self.get_deferred_fields() + if not ({'id', 'object_id', 'object_role_id'} & def_fields): + if self.object_role_id and not self.object_id: + # Cache fields from the associated object_role + self.object_id = self.object_role.object_id + self.content_type_id = self.object_role.content_type_id + self.role_definition_id = self.object_role.role_definition_id class RoleUserAssignment(AssignmentBase): diff --git a/test_app/tests/rbac/models/test_role_assignments.py b/test_app/tests/rbac/models/test_role_assignments.py new file mode 100644 index 000000000..4d739abc6 --- /dev/null +++ b/test_app/tests/rbac/models/test_role_assignments.py @@ -0,0 +1,15 @@ +import pytest + +from ansible_base.rbac.models import RoleUserAssignment + + +@pytest.mark.django_db +def test_load_assignment_list(rando, inventory, inv_rd): + assignment = inv_rd.give_permission(rando, inventory) + assert assignment.id in [asmt.id for asmt in RoleUserAssignment.objects.only('id')] + + +@pytest.mark.django_db +def test_load_assignment_property(rando, inventory, inv_rd): + assignment = inv_rd.give_permission(rando, inventory) + assert assignment.object_id in [int(asmt.object_id) for asmt in RoleUserAssignment.objects.only('object_id')]