Skip to content

Commit 669d35e

Browse files
committed
Solve problem of new objects and stuff like that
1 parent 354dfd3 commit 669d35e

File tree

2 files changed

+46
-13
lines changed

2 files changed

+46
-13
lines changed

ansible_base/rbac/service_api/serializers.py

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,45 @@
99
from ..remote import RemoteObject
1010

1111

12+
class ObjectAnsibleIdField(serializers.Field):
13+
"""
14+
Field for object_ansible_id that supports both annotation optimization and fallback.
15+
16+
For read operations: Uses annotation when available, falls back to manual lookup.
17+
For write operations: Converts ansible_id to object_id for internal use.
18+
"""
19+
20+
def to_representation(self, obj):
21+
"""Get object_ansible_id, using annotation when available, falling back to manual lookup"""
22+
# First try to use the annotation from the queryset (for optimized list operations)
23+
if hasattr(obj, '_object_ansible_id_annotation') and obj._object_ansible_id_annotation:
24+
return str(obj._object_ansible_id_annotation)
25+
26+
# Fallback for cases where annotation is not available (creation, etc.)
27+
if not obj.content_type_id or not obj.object_id:
28+
return None
29+
30+
content_object = obj.content_object
31+
if isinstance(content_object, RemoteObject):
32+
return None
33+
if hasattr(content_object, 'resource'):
34+
return str(content_object.resource.ansible_id)
35+
return None
36+
37+
def to_internal_value(self, value):
38+
"""Convert object_ansible_id to object_id for internal use"""
39+
if not value:
40+
return None
41+
42+
from ansible_base.resource_registry.models import Resource
43+
44+
try:
45+
resource = Resource.objects.get(ansible_id=value)
46+
return resource.object_id
47+
except Resource.DoesNotExist:
48+
raise serializers.ValidationError("Resource with this ansible_id does not exist.")
49+
50+
1251
class DABContentTypeSerializer(serializers.ModelSerializer):
1352
parent_content_type = serializers.SlugRelatedField(read_only=True, slug_field='api_slug')
1453

@@ -32,7 +71,7 @@ class BaseAssignmentSerializer(serializers.ModelSerializer):
3271
content_type = serializers.SlugRelatedField(read_only=True, slug_field='api_slug')
3372
role_definition = serializers.SlugRelatedField(slug_field='name', queryset=RoleDefinition.objects.all())
3473
created_by_ansible_id = ActorAnsibleIdField(source='created_by', required=False, allow_null=True)
35-
object_ansible_id = serializers.UUIDField(read_only=True, allow_null=True)
74+
object_ansible_id = ObjectAnsibleIdField(source='object_id', required=False, allow_null=True)
3675
object_id = serializers.CharField(allow_blank=True, required=False, allow_null=True)
3776
from_service = serializers.CharField(write_only=True)
3877

@@ -44,22 +83,16 @@ def validate(self, attrs):
4483
4584
So this does the mutual validation to assure we have sufficient data.
4685
"""
47-
has_oid = bool(self.initial_data.get('object_id'))
48-
has_oaid = bool(self.initial_data.get('object_ansible_id'))
49-
5086
rd = attrs['role_definition']
87+
has_object_id = 'object_id' in attrs and attrs['object_id']
88+
5189
if rd.content_type_id:
52-
if not self.partial and not has_oid and not has_oaid:
90+
if not self.partial and not has_object_id:
5391
raise serializers.ValidationError("You must provide either 'object_id' or 'object_ansible_id'.")
54-
elif not has_oaid:
55-
# need to remove blank and null fields or else it can overwrite the non-null non-blank field
56-
attrs['object_id'] = self.initial_data['object_id']
5792
else:
58-
if has_oaid or has_oid:
93+
if has_object_id:
5994
raise serializers.ValidationError("Can not provide either 'object_id' or 'object_ansible_id' for system role")
6095

61-
# NOTE: right now not enforcing the case you provide both, could check for consistency later
62-
6396
return super().validate(attrs)
6497

6598
def find_existing_assignment(self, queryset):

ansible_base/rbac/service_api/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class ServiceRoleUserAssignmentViewSet(BaseSerivceRoleAssignmentViewSet):
126126
"""List of user assignments for cross-service communication"""
127127

128128
queryset = RoleUserAssignment.objects.prefetch_related('user__resource__content_type', *prefetch_related).annotate(
129-
object_ansible_id=resource_ansible_id_expr()
129+
_object_ansible_id_annotation=resource_ansible_id_expr()
130130
)
131131
serializer_class = service_serializers.ServiceRoleUserAssignmentSerializer
132132
filter_backends = AnsibleBaseDjangoAppApiView.filter_backends + [
@@ -147,7 +147,7 @@ class ServiceRoleTeamAssignmentViewSet(BaseSerivceRoleAssignmentViewSet):
147147
"""List of team role assignments for cross-service communication"""
148148

149149
queryset = RoleTeamAssignment.objects.prefetch_related('team__resource__content_type', *prefetch_related).annotate(
150-
object_ansible_id=resource_ansible_id_expr()
150+
_object_ansible_id_annotation=resource_ansible_id_expr()
151151
)
152152
serializer_class = service_serializers.ServiceRoleTeamAssignmentSerializer
153153
filter_backends = AnsibleBaseDjangoAppApiView.filter_backends + [

0 commit comments

Comments
 (0)