Skip to content

Commit 66f0b57

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 3520c7b commit 66f0b57

File tree

3 files changed

+48
-22
lines changed

3 files changed

+48
-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: 6 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),
@@ -774,10 +776,11 @@ def test_api_document_accesses_update_administrator_except_owner(
774776

775777
access.refresh_from_db()
776778
updated_values = serializers.DocumentAccessSerializer(instance=access).data
777-
if field == "role":
779+
if field in ["role", "max_role"]:
778780
assert updated_values == {
779781
**old_values,
780782
"role": new_values["role"],
783+
"max_role": new_values["role"],
781784
}
782785
else:
783786
assert updated_values == old_values
@@ -950,10 +953,11 @@ def test_api_document_accesses_update_owner(
950953
access.refresh_from_db()
951954
updated_values = serializers.DocumentAccessSerializer(instance=access).data
952955

953-
if field == "role":
956+
if field in ["role", "max_role"]:
954957
assert updated_values == {
955958
**old_values,
956959
"role": new_values["role"],
960+
"max_role": new_values["role"],
957961
}
958962
else:
959963
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)