diff --git a/awx/api/views.py b/awx/api/views.py index 26e13ed59d..021a515358 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -578,49 +578,37 @@ class OrganizationList(ListCreateAPIView): return full_context db_results = {} - org_qs = self.request.user.get_queryset(self.model) + org_qs = self.model.accessible_objects(self.request.user, {"read": True}) org_id_list = org_qs.values('id') if len(org_id_list) == 0: if self.request.method == 'POST': full_context['related_field_counts'] = {} return full_context - inv_qs = self.request.user.get_queryset(Inventory) - project_qs = self.request.user.get_queryset(Project) - user_qs = self.request.user.get_queryset(User) + inv_qs = Inventory.accessible_objects(self.request.user, {"read": True}) + project_qs = Project.accessible_objects(self.request.user, {"read": True}) # Produce counts of Foreign Key relationships db_results['inventories'] = inv_qs\ .values('organization').annotate(Count('organization')).order_by('organization') - db_results['teams'] = self.request.user.get_queryset(Team)\ + db_results['teams'] = Team.accessible_objects( + self.request.user, {"read": True}).values('organization').annotate( + Count('organization')).order_by('organization') + + JT_reference = 'project__organization' + db_results['job_templates'] = JobTemplate.accessible_objects( + self.request.user, {"read": True}).values(JT_reference).annotate( + Count(JT_reference)).order_by(JT_reference) + + db_results['projects'] = project_qs\ .values('organization').annotate(Count('organization')).order_by('organization') - # TODO: When RBAC branch merges, change this to project relationship - JT_reference = 'inventory__organization' - # Extra filter is applied on the inventory, because this catches - # the case of deleted (and purged) inventory - db_results['job_templates'] = self.request.user.get_queryset(JobTemplate)\ - .filter(inventory__in=inv_qs)\ - .values(JT_reference).annotate(Count(JT_reference))\ - .order_by(JT_reference) - - # Produce counts of m2m relationships - db_results['projects'] = Organization.projects.through.objects\ - .filter(project__in=project_qs, organization__in=org_qs)\ - .values('organization')\ - .annotate(Count('organization')).order_by('organization') - - # TODO: When RBAC branch merges, change these to role relation - db_results['users'] = Organization.users.through.objects\ - .filter(user__in=user_qs, organization__in=org_qs)\ - .values('organization')\ - .annotate(Count('organization')).order_by('organization') - - db_results['admins'] = Organization.admins.through.objects\ - .filter(user__in=user_qs, organization__in=org_qs)\ - .values('organization')\ - .annotate(Count('organization')).order_by('organization') + # Other members and admins of organization are always viewable + db_results['users'] = org_qs.annotate( + users=Count('member_role__members', distinct=True), + admins=Count('admin_role__members', distinct=True) + ).values('id', 'users', 'admins') count_context = {} for org in org_id_list: @@ -632,11 +620,17 @@ class OrganizationList(ListCreateAPIView): for res in db_results: if res == 'job_templates': org_reference = JT_reference + elif res == 'users': + org_reference = 'id' else: org_reference = 'organization' for entry in db_results[res]: org_id = entry[org_reference] if org_id in count_context: + if res == 'users': + count_context[org_id]['admins'] = entry['admins'] + count_context[org_id]['users'] = entry['users'] + continue count_context[org_id][res] = entry['%s__count' % org_reference] full_context['related_field_counts'] = count_context diff --git a/awx/main/tests/functional/api/test_organization_counts.py b/awx/main/tests/functional/api/test_organization_counts.py index 8d881fe8a0..6ab5cf2b54 100644 --- a/awx/main/tests/functional/api/test_organization_counts.py +++ b/awx/main/tests/functional/api/test_organization_counts.py @@ -8,9 +8,8 @@ def resourced_organization(organization, project, team, inventory, user): member_user = user('org-member') # Associate one resource of every type with the organization - organization.users.add(member_user) - organization.admins.add(admin_user) - organization.projects.add(project) + organization.member_role.members.add(member_user) + organization.admin_role.members.add(admin_user) # organization.teams.create(name='org-team') # inventory = organization.inventories.create(name="associated-inv") project.jobtemplates.create(name="test-jt", @@ -41,17 +40,17 @@ def test_org_counts_admin(resourced_organization, user, get): def test_org_counts_member(resourced_organization, get): # Check that a non-admin user can only see the full project and # user count, consistent with the RBAC rules - member_user = resourced_organization.users.get(username='org-member') + member_user = resourced_organization.member_role.members.get(username='org-member') response = get(reverse('api:organization_list', args=[]), member_user) assert response.status_code == 200 counts = response.data['results'][0]['summary_fields']['related_field_counts'] assert counts == { - 'users': 1, # User can see themselves - 'admins': 0, + 'users': 1, # Policy is that members can see other users and admins + 'admins': 1, 'job_templates': 0, - 'projects': 1, # Projects are shared with all the organization + 'projects': 0, 'inventories': 0, 'teams': 0 } @@ -118,20 +117,20 @@ def test_JT_associated_with_project(organizations, project, user, get): other_org = two_orgs[1] unrelated_inv = other_org.inventories.create(name='not-in-organization') + organization.projects.add(project) project.jobtemplates.create(name="test-jt", description="test-job-template-desc", inventory=unrelated_inv, playbook="test_playbook.yml") - organization.projects.add(project) response = get(reverse('api:organization_list', args=[]), external_admin) assert response.status_code == 200 org_id = organization.id counts = {} - for i in range(2): - working_id = response.data['results'][i]['id'] - counts[working_id] = response.data['results'][i]['summary_fields']['related_field_counts'] + for org_json in response.data['results']: + working_id = org_json['id'] + counts[working_id] = org_json['summary_fields']['related_field_counts'] assert counts[org_id] == { 'users': 0,