From 2378e2a81b39033ade0e4c6164f6aadb896c5a44 Mon Sep 17 00:00:00 2001
From: Maximilian Moser <maximilian.moser@tuwien.ac.at>
Date: Thu, 12 Sep 2024 19:38:49 +0200
Subject: [PATCH] Deduplicate the high-level permissions

* that's where most of the duplicates are coming from
---
 invenio_config_tuw/permissions/policies.py | 101 +++++++++++----------
 1 file changed, 54 insertions(+), 47 deletions(-)

diff --git a/invenio_config_tuw/permissions/policies.py b/invenio_config_tuw/permissions/policies.py
index 3194b07..91de0dd 100644
--- a/invenio_config_tuw/permissions/policies.py
+++ b/invenio_config_tuw/permissions/policies.py
@@ -5,6 +5,8 @@
 # Invenio-Config-TUW is free software; you can redistribute it and/or modify
 # it under the terms of the MIT License; see LICENSE file for more details.
 
+from typing import Iterable, List
+
 from invenio_administration.generators import Administration
 from invenio_communities.generators import CommunityCurators
 from invenio_communities.permissions import CommunityPermissionPolicy
@@ -43,6 +45,11 @@ from .generators import (
 )
 
 
+def d(i: Iterable) -> List:
+    """Deduplicate the content of the iterable by calling ``list(set(i))``."""
+    return list(set(i))
+
+
 def IfMetadataOnlyAllowed(then_):
     """Don't allow unless metadata-only records are allowed."""
     return IfConfig("RDM_ALLOW_METADATA_ONLY_RECORDS", then_=then_, else_=[])
@@ -105,40 +112,40 @@ class TUWRecordPermissionPolicy(RDMRecordPermissionPolicy):
     #                         and get more permissive from top to bottom
     #
     # fmt: off
-    can_manage             = [TrustedRecordOwners(), RecordCommunitiesAction("curate"), SystemProcess()        ] + shared_access["manage"]   # noqa
-    can_access_draft       = can_manage       + [RecordOwners(), SubmissionReviewer()                          ] + shared_access["preview"]  # noqa
-    can_curate             = can_manage       + [                                                              ] + shared_access["edit"]     # noqa
-    can_review             = can_curate       + [SubmissionReviewer()                                          ]                             # noqa
-    can_preview            = can_access_draft + [UserManager                                                   ]                             # noqa
-    can_view               = can_access_draft + [RecordCommunitiesAction("view"), CommunityInclusionReviewers()] + shared_access["view"]     # noqa
-    can_authenticated      =                    [AuthenticatedUser(), SystemProcess()                          ]                             # noqa
-    can_all                =                    [AnyUser(), SystemProcess()                                    ]                             # noqa
+    can_manage             = d([TrustedRecordOwners(), RecordCommunitiesAction("curate"), SystemProcess()        ] + shared_access["manage"] )  # noqa
+    can_access_draft       = d(can_manage       + [RecordOwners(), SubmissionReviewer()                          ] + shared_access["preview"])  # noqa
+    can_curate             = d(can_manage       + [                                                              ] + shared_access["edit"]   )  # noqa
+    can_review             = d(can_curate       + [SubmissionReviewer()                                          ]                           )  # noqa
+    can_preview            = d(can_access_draft + [UserManager                                                   ]                           )  # noqa
+    can_view               = d(can_access_draft + [RecordCommunitiesAction("view"), CommunityInclusionReviewers()] + shared_access["view"]   )  # noqa
+    can_authenticated      = d(                   [AuthenticatedUser(), SystemProcess()                          ]                           )  # noqa
+    can_all                = d(                   [AnyUser(), SystemProcess()                                    ]                           )  # noqa
 
     # records
-    can_search                   = can_all                                                                                           # noqa
-    can_read                     = [IfRestricted("record", then_=can_view, else_=can_all)                            ]               # noqa
-    can_read_files               = [IfRestricted("files", then_=can_view, else_=can_all), ResourceAccessToken("read")]               # noqa
-    can_get_content_files        = [IfFileIsLocal(then_=can_read_files, else_=[SystemProcess()])                     ]               # noqa
-    can_read_deleted             = [IfRecordDeleted([UserManager, SystemProcess()], else_=can_read)                  ]               # noqa
-    can_read_deleted_files       = can_read_deleted                                                                                  # noqa
-    can_media_read_deleted_files = can_read_deleted_files                                                                            # noqa
-    can_create                   = [TrustedUsers(), DisableIfReadOnly(), SystemProcess()                             ]               # noqa
+    can_search                   = can_all                                                                                                      # noqa
+    can_read                     = [IfRestricted("record", then_=can_view, else_=can_all)                            ]                          # noqa
+    can_read_files               = [IfRestricted("files", then_=can_view, else_=can_all), ResourceAccessToken("read")]                          # noqa
+    can_get_content_files        = [IfFileIsLocal(then_=can_read_files, else_=[SystemProcess()])                     ]                          # noqa
+    can_read_deleted             = [IfRecordDeleted([UserManager, SystemProcess()], else_=can_read)                  ]                          # noqa
+    can_read_deleted_files       = can_read_deleted                                                                                             # noqa
+    can_media_read_deleted_files = can_read_deleted_files                                                                                       # noqa
+    can_create                   = [TrustedUsers(), DisableIfReadOnly(), SystemProcess()                             ]                          # noqa
 
     # drafts
     # > can_manage_files: allow enabling/disabling files
     # > can_manage_record_access: allow restricting access
-    can_search_drafts           = can_authenticated                                                                                  # noqa
-    can_read_draft              = can_preview                                                                                        # noqa
-    can_draft_read_files        = can_preview                                                       + [ResourceAccessToken("read")]  # noqa
-    can_update_draft            = can_review                                                        + [DisableIfReadOnly()        ]  # noqa
-    can_draft_create_files      = can_review                                                        + [DisableIfReadOnly()        ]  # noqa
-    can_draft_set_content_files = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()]),           DisableIfReadOnly()        ]  # noqa
-    can_draft_get_content_files = [IfFileIsLocal(then_=can_draft_read_files, else_=[SystemProcess()]), DisableIfReadOnly()        ]  # noqa
-    can_draft_commit_files      = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()]),           DisableIfReadOnly()        ]  # noqa
-    can_draft_update_files      = can_review                                                        + [DisableIfReadOnly()        ]  # noqa
-    can_draft_delete_files      = can_review                                                        + [DisableIfReadOnly()        ]  # noqa
-    can_manage_files            = [IfNewRecord(then_=can_create, else_=can_review),                    DisableIfReadOnly()        ]  # noqa
-    can_manage_record_access    = [IfNewRecord(then_=can_create, else_=can_review),                    DisableIfReadOnly()        ]  # noqa
+    can_search_drafts           = can_authenticated                                                                                             # noqa
+    can_read_draft              = can_preview                                                                                                   # noqa
+    can_draft_read_files        = can_preview                                                       + [ResourceAccessToken("read")]             # noqa
+    can_update_draft            = can_review                                                        + [DisableIfReadOnly()        ]             # noqa
+    can_draft_create_files      = can_review                                                        + [DisableIfReadOnly()        ]             # noqa
+    can_draft_set_content_files = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()]),           DisableIfReadOnly()        ]             # noqa
+    can_draft_get_content_files = [IfFileIsLocal(then_=can_draft_read_files, else_=[SystemProcess()]), DisableIfReadOnly()        ]             # noqa
+    can_draft_commit_files      = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()]),           DisableIfReadOnly()        ]             # noqa
+    can_draft_update_files      = can_review                                                        + [DisableIfReadOnly()        ]             # noqa
+    can_draft_delete_files      = can_review                                                        + [DisableIfReadOnly()        ]             # noqa
+    can_manage_files            = [IfNewRecord(then_=can_create, else_=can_review),                    DisableIfReadOnly()        ]             # noqa
+    can_manage_record_access    = [IfNewRecord(then_=can_create, else_=can_review),                    DisableIfReadOnly()        ]             # noqa
 
     # PIDs
     can_pid_create         = can_review + [DisableIfReadOnly()]                                                          # noqa
@@ -150,11 +157,11 @@ class TUWRecordPermissionPolicy(RDMRecordPermissionPolicy):
     # actions
     # > can_edit: RecordOwners is needed to not break the 'edit' button on the dashboard (UX)
     # > can_publish: TODO only "data stewards" should be able to publish
-    can_edit               = [IfDeleted(then_=[Disable()], else_=can_curate + [RecordOwners(), DisableIfReadOnly()])]  # noqa
-    can_delete_draft       = can_curate                                                       + [DisableIfReadOnly()]  # noqa
-    can_new_version        = can_curate                                                       + [DisableIfReadOnly()]  # noqa
-    can_lift_embargo       = can_manage                                                       + [DisableIfReadOnly()]  # noqa
-    can_publish            = [TrustedPublisherForNewButTrustedUserForEdits(), SystemProcess(),   DisableIfReadOnly()]  # noqa
+    can_edit               = [IfDeleted(then_=[Disable()], else_=can_curate + [RecordOwners(), DisableIfReadOnly()])]    # noqa
+    can_delete_draft       = can_curate                                                       + [DisableIfReadOnly()]    # noqa
+    can_new_version        = can_curate                                                       + [DisableIfReadOnly()]    # noqa
+    can_lift_embargo       = can_manage                                                       + [DisableIfReadOnly()]    # noqa
+    can_publish            = [TrustedPublisherForNewButTrustedUserForEdits(), SystemProcess(),   DisableIfReadOnly()]    # noqa
 
     # record communities
     # can_add_community:    add a record to a community
@@ -168,24 +175,24 @@ class TUWRecordPermissionPolicy(RDMRecordPermissionPolicy):
     #
     # media files (drafts)
     #
-    can_draft_media_create_files      = can_review                                                                      # noqa
-    can_draft_media_read_files        = can_review                                                                      # noqa
-    can_draft_media_set_content_files = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()])]                      # noqa
-    can_draft_media_get_content_files = [IfFileIsLocal(then_=can_preview, else_=[SystemProcess()])]                     # noqa
-    can_draft_media_commit_files      = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()])]                      # noqa
-    can_draft_media_update_files      = can_review                                                                      # noqa
-    can_draft_media_delete_files      = can_review                                                                      # noqa
+    can_draft_media_create_files      = can_review                                                                       # noqa
+    can_draft_media_read_files        = can_review                                                                       # noqa
+    can_draft_media_set_content_files = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()])]                       # noqa
+    can_draft_media_get_content_files = [IfFileIsLocal(then_=can_preview, else_=[SystemProcess()])]                      # noqa
+    can_draft_media_commit_files      = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()])]                       # noqa
+    can_draft_media_update_files      = can_review                                                                       # noqa
+    can_draft_media_delete_files      = can_review                                                                       # noqa
 
     #
     # media files (records)
     #
-    can_media_read_files        = [IfRestricted("record", then_=can_view, else_=can_all), ResourceAccessToken("read")]  # noqa
-    can_media_get_content_files = [IfFileIsLocal(then_=can_read, else_=[SystemProcess()])]                              # noqa
-    can_media_create_files      = [Disable()]                                                                           # noqa
-    can_media_set_content_files = [Disable()]                                                                           # noqa
-    can_media_commit_files      = [Disable()]                                                                           # noqa
-    can_media_update_files      = [Disable()]                                                                           # noqa
-    can_media_delete_files      = [Disable()]                                                                           # noqa
+    can_media_read_files        = [IfRestricted("record", then_=can_view, else_=can_all), ResourceAccessToken("read")]   # noqa
+    can_media_get_content_files = [IfFileIsLocal(then_=can_read, else_=[SystemProcess()])]                               # noqa
+    can_media_create_files      = [Disable()]                                                                            # noqa
+    can_media_set_content_files = [Disable()]                                                                            # noqa
+    can_media_commit_files      = [Disable()]                                                                            # noqa
+    can_media_update_files      = [Disable()]                                                                            # noqa
+    can_media_delete_files      = [Disable()]                                                                            # noqa
 
     #
     # record deletion workflows
-- 
GitLab