mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 01:47:35 -02:30
Merge pull request #1414 from anoek/access-list-updates
Updated access_list to include team information for indirect access
This commit is contained in:
@@ -1469,6 +1469,16 @@ class RoleSerializer(BaseSerializer):
|
|||||||
class ResourceAccessListElementSerializer(UserSerializer):
|
class ResourceAccessListElementSerializer(UserSerializer):
|
||||||
|
|
||||||
def to_representation(self, user):
|
def to_representation(self, user):
|
||||||
|
'''
|
||||||
|
With this method we derive "direct" and "indirect" access lists. Contained
|
||||||
|
in the direct access list are all the roles the user is a member of, and
|
||||||
|
all of the roles that are directly granted to any teams that the user is a
|
||||||
|
member of.
|
||||||
|
|
||||||
|
The indirect access list is a list of all of the roles that the user is
|
||||||
|
a member of that are ancestors of any roles that grant permissions to
|
||||||
|
the resource.
|
||||||
|
'''
|
||||||
ret = super(ResourceAccessListElementSerializer, self).to_representation(user)
|
ret = super(ResourceAccessListElementSerializer, self).to_representation(user)
|
||||||
object_id = self.context['view'].object_id
|
object_id = self.context['view'].object_id
|
||||||
obj = self.context['view'].resource_model.objects.get(pk=object_id)
|
obj = self.context['view'].resource_model.objects.get(pk=object_id)
|
||||||
@@ -1485,17 +1495,60 @@ class ResourceAccessListElementSerializer(UserSerializer):
|
|||||||
role_dict['related'] = reverse_gfk(role.content_object)
|
role_dict['related'] = reverse_gfk(role.content_object)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return { 'role': role_dict, 'permissions': get_role_permissions_on_resource(obj, role)}
|
return { 'role': role_dict, 'permissions': get_role_permissions_on_resource(obj, role)}
|
||||||
|
|
||||||
content_type = ContentType.objects.get_for_model(obj)
|
def format_team_role_perm(team_role, permissive_role_ids):
|
||||||
direct_permissive_role_ids = RolePermission.objects.filter(content_type=content_type, object_id=obj.id).values_list('role__id')
|
role = team_role.children.filter(id__in=permissive_role_ids)[0]
|
||||||
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]
|
|
||||||
|
|
||||||
|
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')
|
||||||
all_permissive_role_ids = RolePermission.objects.filter(content_type=content_type, object_id=obj.id).values_list('role__ancestors__id')
|
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]
|
direct_access_roles = user.roles \
|
||||||
|
.filter(id__in=direct_permissive_role_ids).all()
|
||||||
|
|
||||||
|
direct_team_roles = Role.objects \
|
||||||
|
.filter(content_type=team_content_type,
|
||||||
|
members=user,
|
||||||
|
children__in=direct_permissive_role_ids)
|
||||||
|
|
||||||
|
indirect_team_roles = Role.objects \
|
||||||
|
.filter(content_type=team_content_type,
|
||||||
|
members=user,
|
||||||
|
children__in=all_permissive_role_ids) \
|
||||||
|
.exclude(id__in=direct_team_roles)
|
||||||
|
|
||||||
|
indirect_access_roles = user.roles \
|
||||||
|
.filter(id__in=all_permissive_role_ids) \
|
||||||
|
.exclude(id__in=direct_permissive_role_ids) \
|
||||||
|
.exclude(id__in=direct_team_roles) \
|
||||||
|
.exclude(id__in=indirect_team_roles)
|
||||||
|
|
||||||
|
ret['summary_fields']['direct_access'] \
|
||||||
|
= [format_role_perm(r) for r in direct_access_roles] \
|
||||||
|
+ [format_team_role_perm(r, direct_permissive_role_ids) for r in direct_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 indirect_team_roles]
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
57
awx/main/tests/functional/api/test_resource_access_lists.py
Normal file
57
awx/main/tests/functional/api/test_resource_access_lists.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_indirect_access_list(get, organization, project, team_factory, user, admin):
|
||||||
|
project_admin = user('project_admin')
|
||||||
|
org_admin_team_member = user('org_admin_team_member')
|
||||||
|
project_admin_team_member = user('project_admin_team_member')
|
||||||
|
|
||||||
|
org_admin_team = team_factory('org-admin-team')
|
||||||
|
project_admin_team = team_factory('project-admin-team')
|
||||||
|
|
||||||
|
project.admin_role.members.add(project_admin)
|
||||||
|
org_admin_team.member_role.members.add(org_admin_team_member)
|
||||||
|
org_admin_team.member_role.children.add(organization.admin_role)
|
||||||
|
project_admin_team.member_role.members.add(project_admin_team_member)
|
||||||
|
project_admin_team.member_role.children.add(project.admin_role)
|
||||||
|
|
||||||
|
result = get(reverse('api:project_access_list', args=(project.id,)), admin)
|
||||||
|
assert result.status_code == 200
|
||||||
|
|
||||||
|
# Result should be:
|
||||||
|
# project_admin should have direct access,
|
||||||
|
# project_team_admin should have "direct" access through being a team member -> project admin,
|
||||||
|
# org_admin_team_member should have indirect access through being a team member -> org admin -> project admin,
|
||||||
|
# admin should have access through system admin -> org admin -> project admin
|
||||||
|
assert result.data['count'] == 4
|
||||||
|
|
||||||
|
project_admin_res = [r for r in result.data['results'] if r['id'] == project_admin.id][0]
|
||||||
|
org_admin_team_member_res = [r for r in result.data['results'] if r['id'] == org_admin_team_member.id][0]
|
||||||
|
project_admin_team_member_res = [r for r in result.data['results'] if r['id'] == project_admin_team_member.id][0]
|
||||||
|
admin_res = [r for r in result.data['results'] if r['id'] == admin.id][0]
|
||||||
|
|
||||||
|
assert len(project_admin_res['summary_fields']['direct_access']) == 1
|
||||||
|
assert len(project_admin_res['summary_fields']['indirect_access']) == 0
|
||||||
|
assert len(org_admin_team_member_res['summary_fields']['direct_access']) == 0
|
||||||
|
assert len(org_admin_team_member_res['summary_fields']['indirect_access']) == 1
|
||||||
|
assert len(admin_res['summary_fields']['direct_access']) == 0
|
||||||
|
assert len(admin_res['summary_fields']['indirect_access']) == 1
|
||||||
|
|
||||||
|
project_admin_entry = project_admin_res['summary_fields']['direct_access'][0]['role']
|
||||||
|
assert project_admin_entry['id'] == project.admin_role.id
|
||||||
|
|
||||||
|
project_admin_team_member_entry = project_admin_team_member_res['summary_fields']['direct_access'][0]['role']
|
||||||
|
assert project_admin_team_member_entry['id'] == project.admin_role.id
|
||||||
|
assert project_admin_team_member_entry['team_id'] == project_admin_team.id
|
||||||
|
assert project_admin_team_member_entry['team_name'] == project_admin_team.name
|
||||||
|
|
||||||
|
org_admin_team_member_entry = org_admin_team_member_res['summary_fields']['indirect_access'][0]['role']
|
||||||
|
assert org_admin_team_member_entry['id'] == organization.admin_role.id
|
||||||
|
assert org_admin_team_member_entry['team_id'] == org_admin_team.id
|
||||||
|
assert org_admin_team_member_entry['team_name'] == org_admin_team.name
|
||||||
|
|
||||||
|
admin_entry = admin_res['summary_fields']['indirect_access'][0]['role']
|
||||||
|
assert admin_entry['name'] == 'System Administrator'
|
||||||
|
|
||||||
@@ -389,20 +389,6 @@ def test_role_children(get, team, admin, role):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# /resource/<id>/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
|
# Generics
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in New Issue
Block a user