Skip to content

Commit 235b322

Browse files
committed
Optimize object_ansible_id
1 parent 6a15b85 commit 235b322

File tree

2 files changed

+20
-30
lines changed

2 files changed

+20
-30
lines changed

ansible_base/rbac/service_api/serializers.py

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,44 +25,17 @@ class Meta:
2525
fields = ['api_slug', 'codename', 'content_type', 'name']
2626

2727

28-
class ObjectIDAnsibleIDField(serializers.Field):
29-
"This is an ansible_id field intended to be used with source pointing to object_id, so, does conversion"
30-
31-
def to_representation(self, value):
32-
"The source for this field is object_id, which is ignored, use content_object instead"
33-
assignment = getattr(self, "_this_assignment", None)
34-
if not assignment:
35-
return None
36-
content_object = assignment.content_object
37-
if isinstance(content_object, RemoteObject):
38-
return None
39-
if hasattr(content_object, 'resource'):
40-
return str(content_object.resource.ansible_id)
41-
return None
42-
43-
def to_internal_value(self, value):
44-
"Targeting object_id, this converts ansible_id into object_id"
45-
resource_cls = apps.get_model('dab_resource_registry', 'Resource')
46-
resource = resource_cls.objects.get(ansible_id=value)
47-
return resource.object_id
48-
49-
5028
assignment_common_fields = ('created', 'created_by_ansible_id', 'object_id', 'object_ansible_id', 'content_type', 'role_definition')
5129

5230

5331
class BaseAssignmentSerializer(serializers.ModelSerializer):
5432
content_type = serializers.SlugRelatedField(read_only=True, slug_field='api_slug')
5533
role_definition = serializers.SlugRelatedField(slug_field='name', queryset=RoleDefinition.objects.all())
5634
created_by_ansible_id = ActorAnsibleIdField(source='created_by', required=False, allow_null=True)
57-
object_ansible_id = ObjectIDAnsibleIDField(source='object_id', required=False, allow_null=True)
35+
object_ansible_id = serializers.UUIDField(read_only=True, allow_null=True)
5836
object_id = serializers.CharField(allow_blank=True, required=False, allow_null=True)
5937
from_service = serializers.CharField(write_only=True)
6038

61-
def to_representation(self, instance):
62-
# hack to surface content_object for ObjectIDAnsibleIDField
63-
self.fields["object_ansible_id"]._this_assignment = instance
64-
return super().to_representation(instance)
65-
6639
def get_created_by_ansible_id(self, obj):
6740
return str(obj.created_by.resource.ansible_id)
6841

ansible_base/rbac/service_api/views.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from django.db import transaction
2+
from django.db.models import OuterRef, Subquery
23
from rest_framework import permissions, status, viewsets
34
from rest_framework.decorators import action
45
from rest_framework.response import Response
56
from rest_framework.viewsets import GenericViewSet, mixins
67

78
from ansible_base.lib.utils.views.django_app_api import AnsibleBaseDjangoAppApiView
89
from ansible_base.lib.utils.views.permissions import try_add_oauth2_scope_permission
10+
from ansible_base.resource_registry.models import Resource
911
from ansible_base.resource_registry.views import HasResourceRegistryPermissions
1012
from ansible_base.rest_filters.rest_framework import ansible_id_backend
1113

@@ -109,10 +111,23 @@ def perform_destroy(self, instance):
109111
instance.role_definition.remove_global_permission(instance.actor)
110112

111113

114+
def resource_ansible_id_expr(ct_field='content_type_id', oid_field='object_id'):
115+
return Subquery(
116+
Resource.objects.filter(
117+
content_type_id=OuterRef(ct_field),
118+
object_id=OuterRef(oid_field),
119+
).values(
120+
'ansible_id'
121+
)[:1]
122+
)
123+
124+
112125
class ServiceRoleUserAssignmentViewSet(BaseSerivceRoleAssignmentViewSet):
113126
"""List of user assignments for cross-service communication"""
114127

115-
queryset = RoleUserAssignment.objects.prefetch_related('user__resource__content_type', 'content_object', *prefetch_related)
128+
queryset = RoleUserAssignment.objects.prefetch_related('user__resource__content_type', *prefetch_related).annotate(
129+
object_ansible_id=resource_ansible_id_expr()
130+
)
116131
serializer_class = service_serializers.ServiceRoleUserAssignmentSerializer
117132
filter_backends = AnsibleBaseDjangoAppApiView.filter_backends + [
118133
ansible_id_backend.UserAnsibleIdAliasFilterBackend,
@@ -131,7 +146,9 @@ def unassign(self, request):
131146
class ServiceRoleTeamAssignmentViewSet(BaseSerivceRoleAssignmentViewSet):
132147
"""List of team role assignments for cross-service communication"""
133148

134-
queryset = RoleTeamAssignment.objects.prefetch_related('team__resource__content_type', 'content_object', *prefetch_related)
149+
queryset = RoleTeamAssignment.objects.prefetch_related('team__resource__content_type', *prefetch_related).annotate(
150+
object_ansible_id=resource_ansible_id_expr()
151+
)
135152
serializer_class = service_serializers.ServiceRoleTeamAssignmentSerializer
136153
filter_backends = AnsibleBaseDjangoAppApiView.filter_backends + [
137154
ansible_id_backend.TeamAnsibleIdAliasFilterBackend,

0 commit comments

Comments
 (0)