Skip to content

Commit 990fee6

Browse files
committed
✨(backend) add computed link reach and role to document API
On a document, we need to display the status of the link (reach and role) taking into account the ancestors link reach/role as well as the current document.
1 parent dda402f commit 990fee6

10 files changed

+206
-2
lines changed

src/backend/core/api/serializers.py

+8
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ class Meta:
181181
"abilities",
182182
"ancestors_link_reach",
183183
"ancestors_link_role",
184+
"computed_link_reach",
185+
"computed_link_role",
184186
"created_at",
185187
"creator",
186188
"depth",
@@ -201,6 +203,8 @@ class Meta:
201203
"abilities",
202204
"ancestors_link_reach",
203205
"ancestors_link_role",
206+
"computed_link_reach",
207+
"computed_link_role",
204208
"created_at",
205209
"creator",
206210
"depth",
@@ -257,6 +261,8 @@ class Meta:
257261
"abilities",
258262
"ancestors_link_reach",
259263
"ancestors_link_role",
264+
"computed_link_reach",
265+
"computed_link_role",
260266
"content",
261267
"created_at",
262268
"creator",
@@ -278,6 +284,8 @@ class Meta:
278284
"abilities",
279285
"ancestors_link_reach",
280286
"ancestors_link_role",
287+
"computed_link_reach",
288+
"computed_link_role",
281289
"created_at",
282290
"creator",
283291
"depth",

src/backend/core/models.py

+28
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ def __init__(self, *args, **kwargs):
493493
"""Initialize cache property."""
494494
super().__init__(*args, **kwargs)
495495
self._ancestors_link_definition = None
496+
self._computed_link_definition = None
496497

497498
def save(self, *args, **kwargs):
498499
"""Write content to object storage only if _content has changed."""
@@ -716,6 +717,11 @@ def compute_ancestors_links_paths_mapping(self):
716717

717718
return paths_links_mapping
718719

720+
@property
721+
def link_definition(self):
722+
"""Returns link reach/role as a definition in dictionary format."""
723+
return {"link_reach": self.link_reach, "link_role": self.link_role}
724+
719725
@property
720726
def ancestors_link_definition(self):
721727
"""Link defintion equivalent to all document's ancestors."""
@@ -746,6 +752,28 @@ def ancestors_link_role(self):
746752
"""Link role equivalent to all document's ancestors."""
747753
return self.ancestors_link_definition["link_role"]
748754

755+
@property
756+
def computed_link_definition(self):
757+
"""
758+
Link reach/role on the document, combining inherited ancestors' link
759+
definitions and the document's own link definition.
760+
"""
761+
if getattr(self, "_computed_link_definition", None) is None:
762+
self._computed_link_definition = get_equivalent_link_definition(
763+
[self.ancestors_link_definition, self.link_definition]
764+
)
765+
return self._computed_link_definition
766+
767+
@property
768+
def computed_link_reach(self):
769+
"""Actual link reach on the document."""
770+
return self.computed_link_definition["link_reach"]
771+
772+
@property
773+
def computed_link_role(self):
774+
"""Actual link role on the document."""
775+
return self.computed_link_definition["link_role"]
776+
749777
def get_abilities(self, user):
750778
"""
751779
Compute and return abilities for a given user on the document.

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

+28
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ def test_api_documents_children_list_anonymous_public_standalone(
3737
"abilities": child1.get_abilities(AnonymousUser()),
3838
"ancestors_link_reach": "public",
3939
"ancestors_link_role": document.link_role,
40+
"computed_link_reach": "public",
41+
"computed_link_role": child1.computed_link_role,
4042
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
4143
"creator": str(child1.creator.id),
4244
"depth": 2,
@@ -57,6 +59,8 @@ def test_api_documents_children_list_anonymous_public_standalone(
5759
"abilities": child2.get_abilities(AnonymousUser()),
5860
"ancestors_link_reach": "public",
5961
"ancestors_link_role": document.link_role,
62+
"computed_link_reach": "public",
63+
"computed_link_role": child2.computed_link_role,
6064
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
6165
"creator": str(child2.creator.id),
6266
"depth": 2,
@@ -107,6 +111,8 @@ def test_api_documents_children_list_anonymous_public_parent(django_assert_num_q
107111
"abilities": child1.get_abilities(AnonymousUser()),
108112
"ancestors_link_reach": child1.ancestors_link_reach,
109113
"ancestors_link_role": child1.ancestors_link_role,
114+
"computed_link_reach": child1.computed_link_reach,
115+
"computed_link_role": child1.computed_link_role,
110116
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
111117
"creator": str(child1.creator.id),
112118
"depth": 4,
@@ -127,6 +133,8 @@ def test_api_documents_children_list_anonymous_public_parent(django_assert_num_q
127133
"abilities": child2.get_abilities(AnonymousUser()),
128134
"ancestors_link_reach": child2.ancestors_link_reach,
129135
"ancestors_link_role": child2.ancestors_link_role,
136+
"computed_link_reach": child2.computed_link_reach,
137+
"computed_link_role": child2.computed_link_role,
130138
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
131139
"creator": str(child2.creator.id),
132140
"depth": 4,
@@ -196,6 +204,8 @@ def test_api_documents_children_list_authenticated_unrelated_public_or_authentic
196204
"abilities": child1.get_abilities(user),
197205
"ancestors_link_reach": reach,
198206
"ancestors_link_role": document.link_role,
207+
"computed_link_reach": child1.computed_link_reach,
208+
"computed_link_role": child1.computed_link_role,
199209
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
200210
"creator": str(child1.creator.id),
201211
"depth": 2,
@@ -216,6 +226,8 @@ def test_api_documents_children_list_authenticated_unrelated_public_or_authentic
216226
"abilities": child2.get_abilities(user),
217227
"ancestors_link_reach": reach,
218228
"ancestors_link_role": document.link_role,
229+
"computed_link_reach": child2.computed_link_reach,
230+
"computed_link_role": child2.computed_link_role,
219231
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
220232
"creator": str(child2.creator.id),
221233
"depth": 2,
@@ -271,6 +283,8 @@ def test_api_documents_children_list_authenticated_public_or_authenticated_paren
271283
"abilities": child1.get_abilities(user),
272284
"ancestors_link_reach": child1.ancestors_link_reach,
273285
"ancestors_link_role": child1.ancestors_link_role,
286+
"computed_link_reach": child1.computed_link_reach,
287+
"computed_link_role": child1.computed_link_role,
274288
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
275289
"creator": str(child1.creator.id),
276290
"depth": 4,
@@ -291,6 +305,8 @@ def test_api_documents_children_list_authenticated_public_or_authenticated_paren
291305
"abilities": child2.get_abilities(user),
292306
"ancestors_link_reach": child2.ancestors_link_reach,
293307
"ancestors_link_role": child2.ancestors_link_role,
308+
"computed_link_reach": child2.computed_link_reach,
309+
"computed_link_role": child2.computed_link_role,
294310
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
295311
"creator": str(child2.creator.id),
296312
"depth": 4,
@@ -373,6 +389,8 @@ def test_api_documents_children_list_authenticated_related_direct(
373389
"abilities": child1.get_abilities(user),
374390
"ancestors_link_reach": document.link_reach,
375391
"ancestors_link_role": link_role,
392+
"computed_link_reach": child1.computed_link_reach,
393+
"computed_link_role": child1.computed_link_role,
376394
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
377395
"creator": str(child1.creator.id),
378396
"depth": 2,
@@ -393,6 +411,8 @@ def test_api_documents_children_list_authenticated_related_direct(
393411
"abilities": child2.get_abilities(user),
394412
"ancestors_link_reach": document.link_reach,
395413
"ancestors_link_role": link_role,
414+
"computed_link_reach": child2.computed_link_reach,
415+
"computed_link_role": child2.computed_link_role,
396416
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
397417
"creator": str(child2.creator.id),
398418
"depth": 2,
@@ -451,6 +471,8 @@ def test_api_documents_children_list_authenticated_related_parent(
451471
"abilities": child1.get_abilities(user),
452472
"ancestors_link_reach": "restricted",
453473
"ancestors_link_role": None,
474+
"computed_link_reach": child1.computed_link_reach,
475+
"computed_link_role": child1.computed_link_role,
454476
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
455477
"creator": str(child1.creator.id),
456478
"depth": 4,
@@ -471,6 +493,8 @@ def test_api_documents_children_list_authenticated_related_parent(
471493
"abilities": child2.get_abilities(user),
472494
"ancestors_link_reach": "restricted",
473495
"ancestors_link_role": None,
496+
"computed_link_reach": child2.computed_link_reach,
497+
"computed_link_role": child2.computed_link_role,
474498
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
475499
"creator": str(child2.creator.id),
476500
"depth": 4,
@@ -581,6 +605,8 @@ def test_api_documents_children_list_authenticated_related_team_members(
581605
"abilities": child1.get_abilities(user),
582606
"ancestors_link_reach": "restricted",
583607
"ancestors_link_role": None,
608+
"computed_link_reach": child1.computed_link_reach,
609+
"computed_link_role": child1.computed_link_role,
584610
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
585611
"creator": str(child1.creator.id),
586612
"depth": 2,
@@ -601,6 +627,8 @@ def test_api_documents_children_list_authenticated_related_team_members(
601627
"abilities": child2.get_abilities(user),
602628
"ancestors_link_reach": "restricted",
603629
"ancestors_link_role": None,
630+
"computed_link_reach": child2.computed_link_reach,
631+
"computed_link_role": child2.computed_link_role,
604632
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
605633
"creator": str(child2.creator.id),
606634
"depth": 2,

0 commit comments

Comments
 (0)