Skip to content

Commit a51e61c

Browse files
committed
✨(backend) add max ancestors role field to document access endpoint
This field is set only on the list view when all accesses for a given document and all its ancestors are listed. It gives the highest role among all accesses related to each document.
1 parent de242e6 commit a51e61c

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

src/backend/core/api/serializers.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class DocumentAccessSerializer(BaseAccessSerializer):
124124
allow_null=True,
125125
)
126126
user = UserSerializer(read_only=True)
127+
max_ancestors_role = serializers.SerializerMethodField(read_only=True)
127128

128129
class Meta:
129130
model = models.DocumentAccess
@@ -136,8 +137,13 @@ class Meta:
136137
"team",
137138
"role",
138139
"abilities",
140+
"max_ancestors_role",
139141
]
140-
read_only_fields = ["id", "document_id", "abilities"]
142+
read_only_fields = ["id", "document_id", "abilities", "max_ancestors_role"]
143+
144+
def get_max_ancestors_role(self, instance):
145+
"""Return max_ancestors_role if annotated; else None."""
146+
return getattr(instance, "max_ancestors_role", None)
141147

142148

143149
class DocumentAccessLightSerializer(DocumentAccessSerializer):
@@ -155,13 +161,15 @@ class Meta:
155161
"team",
156162
"role",
157163
"abilities",
164+
"max_ancestors_role",
158165
]
159166
read_only_fields = [
160167
"id",
161168
"document_id",
162169
"team",
163170
"role",
164171
"abilities",
172+
"max_ancestors_role",
165173
]
166174

167175

src/backend/core/api/viewsets.py

+6
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,11 @@ def list(self, request, *args, **kwargs):
13991399
path_to_ancestors_roles = defaultdict(list)
14001400
path_to_role = defaultdict(lambda: None)
14011401
for access in accesses:
1402+
key = access.target_key
1403+
key_to_max_ancestors_role[key] = choices.RoleChoices.max(
1404+
key_to_max_ancestors_role.get(key), access.role
1405+
)
1406+
14021407
if access.user_id == user.id or access.team in user.teams:
14031408
parent_path = access.document_path[: -models.Document.steplen]
14041409
if parent_path:
@@ -1420,6 +1425,7 @@ def list(self, request, *args, **kwargs):
14201425
serializer_class = self.get_serializer_class()
14211426
serialized_data = []
14221427
for access in accesses:
1428+
access.max_ancestors_role = key_to_max_ancestors_role[access.target_key]
14231429
access.user_roles_tuple = (
14241430
choices.RoleChoices.max(*path_to_ancestors_roles[access.document_path]),
14251431
path_to_role.get(access.document_path),

src/backend/core/tests/documents/test_api_document_accesses.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ def test_api_document_accesses_list_authenticated_related_non_privileged(
148148
else None,
149149
"team": access.team,
150150
"role": access.role,
151+
"max_ancestors_role": access.role,
151152
"abilities": {
152153
"destroy": False,
153154
"partial_update": False,
@@ -248,6 +249,7 @@ def test_api_document_accesses_list_authenticated_related_privileged(
248249
}
249250
if access.user
250251
else None,
252+
"max_ancestors_role": access.role,
251253
"team": access.team,
252254
"role": access.role,
253255
"abilities": access.get_abilities(user),
@@ -514,6 +516,7 @@ def test_api_document_accesses_retrieve_authenticated_related(
514516
"user": access_user,
515517
"team": "",
516518
"role": access.role,
519+
"max_ancestors_role": None,
517520
"abilities": access.get_abilities(user),
518521
}
519522

@@ -668,7 +671,10 @@ def test_api_document_accesses_update_administrator_except_owner(
668671
access.refresh_from_db()
669672
updated_values = serializers.DocumentAccessSerializer(instance=access).data
670673
if field == "role":
671-
assert updated_values == {**old_values, "role": new_values["role"]}
674+
assert updated_values == {
675+
**old_values,
676+
"role": new_values["role"],
677+
}
672678
else:
673679
assert updated_values == old_values
674680

@@ -836,7 +842,10 @@ def test_api_document_accesses_update_owner(
836842
updated_values = serializers.DocumentAccessSerializer(instance=access).data
837843

838844
if field == "role":
839-
assert updated_values == {**old_values, "role": new_values["role"]}
845+
assert updated_values == {
846+
**old_values,
847+
"role": new_values["role"],
848+
}
840849
else:
841850
assert updated_values == old_values
842851

src/backend/core/tests/documents/test_api_document_accesses_create.py

+3
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ def test_api_document_accesses_create_authenticated_administrator(via, mock_user
169169
"id": str(new_document_access.id),
170170
"team": "",
171171
"role": role,
172+
"max_ancestors_role": None,
172173
"user": other_user,
173174
}
174175
assert len(mail.outbox) == 1
@@ -228,6 +229,7 @@ def test_api_document_accesses_create_authenticated_owner(via, mock_user_teams):
228229
"user": other_user,
229230
"team": "",
230231
"role": role,
232+
"max_ancestors_role": None,
231233
"abilities": new_document_access.get_abilities(user),
232234
}
233235
assert len(mail.outbox) == 1
@@ -293,6 +295,7 @@ def test_api_document_accesses_create_email_in_receivers_language(via, mock_user
293295
"user": other_user_data,
294296
"team": "",
295297
"role": role,
298+
"max_ancestors_role": None,
296299
"abilities": new_document_access.get_abilities(user),
297300
}
298301
assert len(mail.outbox) == index + 1

0 commit comments

Comments
 (0)