diff --git a/awx/api/serializers.py b/awx/api/serializers.py index ebecaa26e1..772784d875 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1485,17 +1485,47 @@ class ResourceAccessListElementSerializer(UserSerializer): role_dict['related'] = reverse_gfk(role.content_object) except: pass - return { 'role': role_dict, 'permissions': get_role_permissions_on_resource(obj, role)} + def format_team_role_perm(team_role, all_permissive_role_ids): + role = team_role.children.filter(id__in=all_permissive_role_ids)[0] + + role_dict = { + 'id': role.id, + 'name': role.name, + 'description': role.description, + 'team_id': team_role.object_id, + 'team_name': team_role.content_object.name + } + try: + role_dict['resource_name'] = role.content_object.name + role_dict['resource_type'] = role.content_type.name + role_dict['related'] = reverse_gfk(role.content_object) + except: + pass + return { 'role': role_dict, 'permissions': get_role_permissions_on_resource(obj, team_role)} + + team_content_type = ContentType.objects.get_for_model(Team) content_type = ContentType.objects.get_for_model(obj) direct_permissive_role_ids = RolePermission.objects.filter(content_type=content_type, object_id=obj.id).values_list('role__id') direct_access_roles = user.roles.filter(id__in=direct_permissive_role_ids).all() ret['summary_fields']['direct_access'] = [format_role_perm(r) for r in direct_access_roles] all_permissive_role_ids = RolePermission.objects.filter(content_type=content_type, object_id=obj.id).values_list('role__ancestors__id') - indirect_access_roles = user.roles.filter(id__in=all_permissive_role_ids).exclude(id__in=direct_permissive_role_ids).all() - ret['summary_fields']['indirect_access'] = [format_role_perm(r) for r in indirect_access_roles] + + team_roles = Role.objects \ + .filter(content_type=team_content_type, + members=user, + children__in=all_permissive_role_ids) + + indirect_access_roles = user.roles \ + .filter(id__in=all_permissive_role_ids) \ + .exclude(id__in=direct_permissive_role_ids) \ + .exclude(id__in=team_roles) + ret['summary_fields']['indirect_access'] \ + = [format_role_perm(r) for r in indirect_access_roles] \ + + [format_team_role_perm(r, all_permissive_role_ids) for r in team_roles] + return ret diff --git a/awx/main/tests/functional/api/test_resource_access_lists.py b/awx/main/tests/functional/api/test_resource_access_lists.py new file mode 100644 index 0000000000..48e261b977 --- /dev/null +++ b/awx/main/tests/functional/api/test_resource_access_lists.py @@ -0,0 +1,41 @@ +import pytest + +from django.core.urlresolvers import reverse + +@pytest.mark.django_db +def test_indirect_access_list(get, organization, project, team, alice, bob, admin): + + project.admin_role.members.add(alice) + team.member_role.members.add(bob) + team.member_role.children.add(organization.admin_role) + + result = get(reverse('api:project_access_list', args=(project.id,)), admin) + assert result.status_code == 200 + + # Result should be alice should have direct access, bob should have + # indirect access through being a team member -> org admin -> project admin, + # and admin should have access through system admin -> org admin -> project admin + assert result.data['count'] == 3 + + alice_res = [r for r in result.data['results'] if r['id'] == alice.id][0] + bob_res = [r for r in result.data['results'] if r['id'] == bob.id][0] + admin_res = [r for r in result.data['results'] if r['id'] == admin.id][0] + + assert len(alice_res['summary_fields']['direct_access']) == 1 + assert len(alice_res['summary_fields']['indirect_access']) == 0 + assert len(bob_res['summary_fields']['direct_access']) == 0 + assert len(bob_res['summary_fields']['indirect_access']) == 1 + assert len(admin_res['summary_fields']['direct_access']) == 0 + assert len(admin_res['summary_fields']['indirect_access']) == 1 + + alice_entry = alice_res['summary_fields']['direct_access'][0]['role'] + assert alice_entry['id'] == project.admin_role.id + + bob_entry = bob_res['summary_fields']['indirect_access'][0]['role'] + assert bob_entry['id'] == organization.admin_role.id + assert bob_entry['team_id'] == team.id + assert bob_entry['team_name'] == team.name + + admin_entry = admin_res['summary_fields']['indirect_access'][0]['role'] + assert admin_entry['name'] == 'System Administrator' + diff --git a/awx/main/tests/functional/test_rbac_api.py b/awx/main/tests/functional/test_rbac_api.py index e50206d3f3..6200a46289 100644 --- a/awx/main/tests/functional/test_rbac_api.py +++ b/awx/main/tests/functional/test_rbac_api.py @@ -389,20 +389,6 @@ def test_role_children(get, team, admin, role): - -# -# /resource//access_list -# - -@pytest.mark.django_db -def test_resource_access_list(get, team, admin, role): - team.member_role.members.add(admin) - url = reverse('api:team_access_list', args=(team.id,)) - res = get(url, admin) - assert res.status_code == 200 - - - # # Generics #