From c24066d3f7366253fa8823ce85d3a9498a5d7f14 Mon Sep 17 00:00:00 2001 From: Samuel Paccoud - DINUM Date: Fri, 9 May 2025 08:05:38 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(backend)=20simplify=20furthe?= =?UTF-8?q?r=20select=20options=20on=20link=20reach/role?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We reduce the number of options even more by treating link reach and link role independently: link reach must be higher than its ancestors' equivalent link reach and link role must be higher than its ancestors' link role. This reduces the number of possibilities but we decided to start with the most restrictive and simple offer and extend it if we realize it faces too many criticism instead of risking to offer too many options that are too complex and must be reduced afterwards. --- src/backend/core/choices.py | 51 +++++-------------- .../core/tests/test_models_documents.py | 11 ++-- 2 files changed, 16 insertions(+), 46 deletions(-) diff --git a/src/backend/core/choices.py b/src/backend/core/choices.py index f1a0e298..e6b97511 100644 --- a/src/backend/core/choices.py +++ b/src/backend/core/choices.py @@ -65,49 +65,22 @@ class LinkReachChoices(PriorityTextChoices): def get_select_options(cls, link_reach, link_role): """ Determines the valid select options for link reach and link role depending on the - list of ancestors' link reach/role definitions. + ancestors' link reach/role given as arguments. Returns: Dictionary mapping possible reach levels to their corresponding possible roles. """ - # If no ancestors, return all options - if not link_reach: - return { - reach: LinkRoleChoices.values if reach != cls.RESTRICTED else None - for reach in cls.values - } - - # Initialize the result for all reaches with possible roles - result = { - reach: set(LinkRoleChoices.values) if reach != cls.RESTRICTED else None - for reach in cls.values - } - - # Handle special rules directly with early returns for efficiency - - if link_role == LinkRoleChoices.EDITOR: - # Rule 1: public/editor → override everything - if link_reach == cls.PUBLIC: - return {cls.PUBLIC: [LinkRoleChoices.EDITOR]} - - # Rule 2: authenticated/editor - if link_reach == cls.AUTHENTICATED: - result[cls.AUTHENTICATED].discard(LinkRoleChoices.READER) - result.pop(cls.RESTRICTED, None) - - if link_role == LinkRoleChoices.READER: - # Rule 3: public/reader - if link_reach == cls.PUBLIC: - result.pop(cls.AUTHENTICATED, None) - result.pop(cls.RESTRICTED, None) - - # Rule 4: authenticated/reader - if link_reach == cls.AUTHENTICATED: - result.pop(cls.RESTRICTED, None) - - # Convert sets to ordered lists where applicable return { - reach: sorted(roles, key=LinkRoleChoices.get_priority) if roles else roles - for reach, roles in result.items() + reach: [ + role + for role in LinkRoleChoices.values + if LinkRoleChoices.get_priority(role) + >= LinkRoleChoices.get_priority(link_role) + ] + if reach != cls.RESTRICTED + else None + for reach in cls.values + if LinkReachChoices.get_priority(reach) + >= LinkReachChoices.get_priority(link_reach) } diff --git a/src/backend/core/tests/test_models_documents.py b/src/backend/core/tests/test_models_documents.py index 1842a09e..dfaf68f3 100644 --- a/src/backend/core/tests/test_models_documents.py +++ b/src/backend/core/tests/test_models_documents.py @@ -1178,7 +1178,6 @@ def test_models_documents_restore_complex_bis(django_assert_num_queries): @pytest.mark.parametrize( "reach, role, select_options", [ - # One ancestor ( "public", "reader", @@ -1198,7 +1197,7 @@ def test_models_documents_restore_complex_bis(django_assert_num_queries): ( "authenticated", "editor", - {"authenticated": ["editor"], "public": ["reader", "editor"]}, + {"authenticated": ["editor"], "public": ["editor"]}, ), ( "restricted", @@ -1214,18 +1213,16 @@ def test_models_documents_restore_complex_bis(django_assert_num_queries): "editor", { "restricted": None, - "authenticated": ["reader", "editor"], - "public": ["reader", "editor"], + "authenticated": ["editor"], + "public": ["editor"], }, ), - # No ancestors (edge case) + # Edge cases ( "public", None, { "public": ["reader", "editor"], - "authenticated": ["reader", "editor"], - "restricted": None, }, ), (