diff --git a/awx/api/serializers.py b/awx/api/serializers.py index e3d02dec13..282a40697f 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -191,6 +191,7 @@ SUMMARIZABLE_FK_FIELDS = { 'webhook_credential': DEFAULT_SUMMARY_FIELDS + ('kind', 'cloud', 'credential_type_id'), 'approved_or_denied_by': ('id', 'username', 'first_name', 'last_name'), 'credential_type': DEFAULT_SUMMARY_FIELDS, + 'resource': ('ansible_id', 'resource_type'), } diff --git a/awx/main/access.py b/awx/main/access.py index c768e74c4c..98a25011d2 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -639,7 +639,10 @@ class UserAccess(BaseAccess): """ model = User - prefetch_related = ('profile',) + prefetch_related = ( + 'profile', + 'resource', + ) def filtered_queryset(self): if settings.ORG_ADMINS_CAN_SEE_ALL_USERS and (self.user.admin_of_organizations.exists() or self.user.auditor_of_organizations.exists()): @@ -835,6 +838,7 @@ class OrganizationAccess(NotificationAttachMixin, BaseAccess): prefetch_related = ( 'created_by', 'modified_by', + 'resource', # dab_resource_registry ) # organization admin_role is not a parent of organization auditor_role notification_attach_roles = ['admin_role', 'auditor_role'] @@ -1303,6 +1307,7 @@ class TeamAccess(BaseAccess): 'created_by', 'modified_by', 'organization', + 'resource', # dab_resource_registry ) def filtered_queryset(self): diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index 3148f44fb5..1a8c088523 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -6,6 +6,8 @@ from django.conf import settings # noqa from django.db import connection from django.db.models.signals import pre_delete # noqa +# django-ansible-base +from ansible_base.resource_registry.fields import AnsibleResourceField from ansible_base.lib.utils.models import prevent_search # AWX @@ -99,6 +101,7 @@ from awx.main.access import get_user_queryset, check_user_access, check_user_acc User.add_to_class('get_queryset', get_user_queryset) User.add_to_class('can_access', check_user_access) User.add_to_class('can_access_with_errors', check_user_access_with_errors) +User.add_to_class('resource', AnsibleResourceField(primary_key_field="id")) def convert_jsonfields(): diff --git a/awx/main/models/organization.py b/awx/main/models/organization.py index 5e90c51ace..bba0bf52c8 100644 --- a/awx/main/models/organization.py +++ b/awx/main/models/organization.py @@ -10,6 +10,8 @@ from django.contrib.sessions.models import Session from django.utils.timezone import now as tz_now from django.utils.translation import gettext_lazy as _ +# django-ansible-base +from ansible_base.resource_registry.fields import AnsibleResourceField # AWX from awx.api.versioning import reverse @@ -103,6 +105,7 @@ class Organization(CommonModel, NotificationFieldsModel, ResourceMixin, CustomVi approval_role = ImplicitRoleField( parent_role='admin_role', ) + resource = AnsibleResourceField(primary_key_field="id") def get_absolute_url(self, request=None): return reverse('api:organization_detail', kwargs={'pk': self.pk}, request=request) @@ -151,6 +154,7 @@ class Team(CommonModelNameNotUnique, ResourceMixin): read_role = ImplicitRoleField( parent_role=['organization.auditor_role', 'member_role'], ) + resource = AnsibleResourceField(primary_key_field="id") def get_absolute_url(self, request=None): return reverse('api:team_detail', kwargs={'pk': self.pk}, request=request) diff --git a/awx/main/tests/functional/dab_resource_registry/test_ansible_id_display.py b/awx/main/tests/functional/dab_resource_registry/test_ansible_id_display.py new file mode 100644 index 0000000000..bf0d550262 --- /dev/null +++ b/awx/main/tests/functional/dab_resource_registry/test_ansible_id_display.py @@ -0,0 +1,39 @@ +import pytest + +from ansible_base.resource_registry.models import Resource + +from awx.api.versioning import reverse + + +def assert_has_resource(list_response, obj=None): + data = list_response.data + assert 'resource' in data['results'][0]['summary_fields'] + resource_data = data['results'][0]['summary_fields']['resource'] + assert resource_data['ansible_id'] + resource = Resource.objects.filter(ansible_id=resource_data['ansible_id']).first() + assert resource + assert resource.content_object + if obj: + objects = [Resource.objects.get(ansible_id=entry['summary_fields']['resource']['ansible_id']).content_object for entry in data['results']] + assert obj in objects + + +@pytest.mark.django_db +def test_organization_ansible_id(organization, admin_user, get): + url = reverse('api:organization_list') + response = get(url=url, user=admin_user, expect=200) + assert_has_resource(response, obj=organization) + + +@pytest.mark.django_db +def test_team_ansible_id(team, admin_user, get): + url = reverse('api:team_list') + response = get(url=url, user=admin_user, expect=200) + assert_has_resource(response, obj=team) + + +@pytest.mark.django_db +def test_user_ansible_id(rando, admin_user, get): + url = reverse('api:user_list') + response = get(url=url, user=admin_user, expect=200) + assert_has_resource(response, obj=rando)