From 4dfd19301ec649a9174f4f71b67d93c5a775207c Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Tue, 30 Apr 2024 10:09:15 -0400 Subject: [PATCH] Partially migrate another user editing condition from AWX --- ansible_base/rbac/policies.py | 10 +++++++++- test_app/tests/rbac/test_policies.py | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/ansible_base/rbac/policies.py b/ansible_base/rbac/policies.py index 86d95adfc..a4af504f0 100644 --- a/ansible_base/rbac/policies.py +++ b/ansible_base/rbac/policies.py @@ -35,6 +35,7 @@ def visible_users(request_user, queryset=None) -> QuerySet: def can_change_user(request_user, target_user) -> bool: + """Tells if the request user can modify details of the target user""" if request_user.is_superuser: return True elif target_user.is_superuser: @@ -43,8 +44,15 @@ def can_change_user(request_user, target_user) -> bool: if not get_setting('MANAGE_ORGANIZATION_AUTH', False): return False + # If the user is not in any organizations, answer can not consider organization permissions org_cls = apps.get_model(settings.ANSIBLE_BASE_ORGANIZATION_MODEL) - return not org_cls.access_qs(target_user, 'member_organization').exclude(pk__in=org_cls.access_ids_qs(request_user, 'change_organization')).exists() + target_user_orgs = org_cls.access_qs(target_user, 'member_organization') + if not target_user_orgs.exists(): + return request_user.is_superuser + + # Organization admins can manage users in their organization + # this requires change permission to all organizations the target user is a member of + return not target_user_orgs.exclude(pk__in=org_cls.access_ids_qs(request_user, 'change_organization')).exists() def check_content_obj_permission(request_user, obj) -> None: diff --git a/test_app/tests/rbac/test_policies.py b/test_app/tests/rbac/test_policies.py index 85dfc899b..2b09310f4 100644 --- a/test_app/tests/rbac/test_policies.py +++ b/test_app/tests/rbac/test_policies.py @@ -11,3 +11,12 @@ def test_org_admin_can_not_change_superuser(org_admin_rd, organization): admin = User.objects.create(username='new-superuser', is_superuser=True) assert not can_change_user(org_admin, admin) + + +@pytest.mark.django_db +def test_unrelated_can_not_change_user(): + alice = User.objects.create(username='alice') + bob = User.objects.create(username='bob') + + for first, second in [(alice, bob), (bob, alice)]: + assert not can_change_user(first, second)