Skip to content

Commit ad6e1f2

Browse files
committed
✨(backend) add max_role field to the document access API endpoint
The frontend needs to know what to display on an access. The maximum role between the access role and the role equivalent to all accesses on the document's ancestors should be computed on the backend.
1 parent 0151d23 commit ad6e1f2

File tree

3 files changed

+49
-22
lines changed

3 files changed

+49
-22
lines changed

src/backend/core/api/serializers.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ class DocumentAccessSerializer(serializers.ModelSerializer):
303303
team = serializers.CharField(required=False, allow_blank=True)
304304
abilities = serializers.SerializerMethodField(read_only=True)
305305
max_ancestors_role = serializers.SerializerMethodField(read_only=True)
306+
max_role = serializers.SerializerMethodField(read_only=True)
306307

307308
class Meta:
308309
model = models.DocumentAccess
@@ -316,8 +317,15 @@ class Meta:
316317
"role",
317318
"abilities",
318319
"max_ancestors_role",
320+
"max_role",
321+
]
322+
read_only_fields = [
323+
"id",
324+
"document",
325+
"abilities",
326+
"max_ancestors_role",
327+
"max_role",
319328
]
320-
read_only_fields = ["id", "document", "abilities", "max_ancestors_role"]
321329

322330
def get_abilities(self, instance) -> dict:
323331
"""Return abilities of the logged-in user on the instance."""
@@ -330,6 +338,13 @@ def get_max_ancestors_role(self, instance):
330338
"""Return max_ancestors_role if annotated; else None."""
331339
return getattr(instance, "max_ancestors_role", None)
332340

341+
def get_max_role(self, instance):
342+
"""Return max_ancestors_role if annotated; else None."""
343+
return choices.RoleChoices.max(
344+
getattr(instance, "max_ancestors_role", None),
345+
instance.role,
346+
)
347+
333348
def update(self, instance, validated_data):
334349
"""Make "user" field readonly but only on update."""
335350
validated_data.pop("team", None)
@@ -353,6 +368,7 @@ class Meta:
353368
"role",
354369
"abilities",
355370
"max_ancestors_role",
371+
"max_role",
356372
]
357373
read_only_fields = [
358374
"id",
@@ -361,6 +377,7 @@ class Meta:
361377
"role",
362378
"abilities",
363379
"max_ancestors_role",
380+
"max_role",
364381
]
365382

366383

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ def test_api_document_accesses_list_authenticated_related_non_privileged(
153153
"team": access.team,
154154
"role": access.role,
155155
"max_ancestors_role": None,
156+
"max_role": access.role,
156157
"abilities": {
157158
"destroy": False,
158159
"partial_update": False,
@@ -253,6 +254,7 @@ def test_api_document_accesses_list_authenticated_related_privileged(
253254
if access.user
254255
else None,
255256
"max_ancestors_role": None,
257+
"max_role": access.role,
256258
"team": access.team,
257259
"role": access.role,
258260
"abilities": access.get_abilities(user),
@@ -617,6 +619,7 @@ def test_api_document_accesses_retrieve_authenticated_related(
617619
"team": "",
618620
"role": access.role,
619621
"max_ancestors_role": None,
622+
"max_role": access.role,
620623
"abilities": access.get_abilities(user),
621624
}
622625

@@ -775,10 +778,11 @@ def test_api_document_accesses_update_administrator_except_owner(
775778

776779
access.refresh_from_db()
777780
updated_values = serializers.DocumentAccessSerializer(instance=access).data
778-
if field == "role":
781+
if field in ["role", "max_role"]:
779782
assert updated_values == {
780783
**old_values,
781784
"role": new_values["role"],
785+
"max_role": new_values["role"],
782786
}
783787
else:
784788
assert updated_values == old_values
@@ -951,10 +955,11 @@ def test_api_document_accesses_update_owner(
951955
access.refresh_from_db()
952956
updated_values = serializers.DocumentAccessSerializer(instance=access).data
953957

954-
if field == "role":
958+
if field in ["role", "max_role"]:
955959
assert updated_values == {
956960
**old_values,
957961
"role": new_values["role"],
962+
"max_role": new_values["role"],
958963
}
959964
else:
960965
assert updated_values == old_values

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

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,11 @@ def test_api_document_accesses_create_authenticated_administrator_share_to_user(
176176
"path": new_document_access.document.path,
177177
},
178178
"id": str(new_document_access.id),
179-
"user": other_user,
180-
"team": "",
181-
"role": role,
182179
"max_ancestors_role": None,
180+
"max_role": role,
181+
"role": role,
182+
"team": "",
183+
"user": other_user,
183184
}
184185
assert len(mail.outbox) == 1
185186
email = mail.outbox[0]
@@ -266,10 +267,11 @@ def test_api_document_accesses_create_authenticated_administrator_share_to_team(
266267
"path": new_document_access.document.path,
267268
},
268269
"id": str(new_document_access.id),
269-
"user": None,
270-
"team": "new-team",
271-
"role": role,
272270
"max_ancestors_role": None,
271+
"max_role": role,
272+
"role": role,
273+
"team": "new-team",
274+
"user": None,
273275
}
274276
assert len(mail.outbox) == 0
275277

@@ -323,17 +325,18 @@ def test_api_document_accesses_create_authenticated_owner_share_to_user(
323325
new_document_access = models.DocumentAccess.objects.filter(user=other_user).get()
324326
other_user = serializers.UserSerializer(instance=other_user).data
325327
assert response.json() == {
328+
"abilities": new_document_access.get_abilities(user),
326329
"document": {
327330
"id": str(new_document_access.document_id),
328-
"path": new_document_access.document.path,
329331
"depth": new_document_access.document.depth,
332+
"path": new_document_access.document.path,
330333
},
331334
"id": str(new_document_access.id),
332-
"user": other_user,
333-
"team": "",
334-
"role": role,
335335
"max_ancestors_role": None,
336-
"abilities": new_document_access.get_abilities(user),
336+
"max_role": role,
337+
"role": role,
338+
"team": "",
339+
"user": other_user,
337340
}
338341
assert len(mail.outbox) == 1
339342
email = mail.outbox[0]
@@ -396,17 +399,18 @@ def test_api_document_accesses_create_authenticated_owner_share_to_team(
396399
new_document_access = models.DocumentAccess.objects.filter(team="new-team").get()
397400
other_user = serializers.UserSerializer(instance=other_user).data
398401
assert response.json() == {
402+
"abilities": new_document_access.get_abilities(user),
399403
"document": {
400404
"id": str(new_document_access.document_id),
401405
"path": new_document_access.document.path,
402406
"depth": new_document_access.document.depth,
403407
},
404408
"id": str(new_document_access.id),
405-
"user": None,
406-
"team": "new-team",
407-
"role": role,
408409
"max_ancestors_role": None,
409-
"abilities": new_document_access.get_abilities(user),
410+
"max_role": role,
411+
"role": role,
412+
"team": "new-team",
413+
"user": None,
410414
}
411415
assert len(mail.outbox) == 0
412416

@@ -457,17 +461,18 @@ def test_api_document_accesses_create_email_in_receivers_language(via, mock_user
457461
).get()
458462
other_user_data = serializers.UserSerializer(instance=other_user).data
459463
assert response.json() == {
464+
"abilities": new_document_access.get_abilities(user),
460465
"document": {
461466
"id": str(new_document_access.document_id),
462467
"path": new_document_access.document.path,
463468
"depth": new_document_access.document.depth,
464469
},
465470
"id": str(new_document_access.id),
466-
"user": other_user_data,
467-
"team": "",
468-
"role": role,
469471
"max_ancestors_role": None,
470-
"abilities": new_document_access.get_abilities(user),
472+
"max_role": role,
473+
"role": role,
474+
"team": "",
475+
"user": other_user_data,
471476
}
472477
assert len(mail.outbox) == index + 1
473478
email = mail.outbox[index]

0 commit comments

Comments
 (0)