From 4c15374b05bb4f708644bd4be2f4058420959206 Mon Sep 17 00:00:00 2001 From: Akita Noek Date: Mon, 25 Apr 2016 14:07:32 -0400 Subject: [PATCH] Optimized (user|team)/:n/roles/ --- awx/api/views.py | 9 ++++++--- awx/main/models/rbac.py | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/awx/api/views.py b/awx/api/views.py index be7dcbb215..3b0942dc65 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -816,7 +816,8 @@ class TeamRolesList(SubListCreateAttachDetachAPIView): def get_queryset(self): team = Team.objects.get(pk=self.kwargs['pk']) - return team.member_role.children.filter(id__in=Role.visible_roles(self.request.user)) + #return team.member_role.children.filter(id__in=Role.visible_roles(self.request.user)) + return Role.filter_visible_roles(self.request.user, team.member_role.children.all()) # XXX: Need to enforce permissions def post(self, request, *args, **kwargs): @@ -1082,8 +1083,10 @@ class UserRolesList(SubListCreateAttachDetachAPIView): permission_classes = (IsAuthenticated,) def get_queryset(self): - #u = User.objects.get(pk=self.kwargs['pk']) - return Role.visible_roles(self.request.user).filter(members__in=[int(self.kwargs['pk']), ]) + u = get_object_or_404(User, pk=self.kwargs['pk']) + if not self.request.user.can_access(User, 'read', u): + raise PermissionDenied() + return Role.filter_visible_roles(self.request.user, u.roles.all()) def post(self, request, *args, **kwargs): # Forbid implicit role creation here diff --git a/awx/main/models/rbac.py b/awx/main/models/rbac.py index ed3e9272d5..54d10e39f1 100644 --- a/awx/main/models/rbac.py +++ b/awx/main/models/rbac.py @@ -357,6 +357,7 @@ class Role(models.Model): 'roles_table': Role._meta.db_table, 'ids': ','.join(str(x) for x in user.roles.values_list('id', flat=True)) } + qs = Role.objects.extra( where = [''' %(roles_table)s.id IN ( @@ -368,6 +369,26 @@ class Role(models.Model): ) return qs + @staticmethod + def filter_visible_roles(user, roles_qs): + sql_params = { + 'ancestors_table': Role.ancestors.through._meta.db_table, + 'parents_table': Role.parents.through._meta.db_table, + 'roles_table': Role._meta.db_table, + 'ids': ','.join(str(x) for x in user.roles.all().values_list('id', flat=True)) + } + + qs = roles_qs.extra( + where = [''' + EXISTS ( + SELECT 1 FROM + %(ancestors_table)s + WHERE (descendent_id = %(roles_table)s.id AND ancestor_id IN (%(ids)s)) + OR (ancestor_id = %(roles_table)s.id AND descendent_id IN (%(ids)s)) + ) ''' % sql_params] + ) + return qs + @staticmethod def singleton(name): role, _ = Role.objects.get_or_create(singleton_name=name, role_field=name)