From d232654c557299a21ad684069aef49a4a1d5ec14 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 7542d375..57427fb9 100644 --- a/src/backend/core/tests/test_models_documents.py +++ b/src/backend/core/tests/test_models_documents.py @@ -1186,7 +1186,6 @@ def test_models_documents_restore_complex_bis(django_assert_num_queries): @pytest.mark.parametrize( "reach, role, select_options", [ - # One ancestor ( "public", "reader", @@ -1206,7 +1205,7 @@ def test_models_documents_restore_complex_bis(django_assert_num_queries): ( "authenticated", "editor", - {"authenticated": ["editor"], "public": ["reader", "editor"]}, + {"authenticated": ["editor"], "public": ["editor"]}, ), ( "restricted", @@ -1222,18 +1221,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, }, ), (