Skip to content

feat: SameAs generator#119

Merged
max-moser merged 1 commit intoinveniosoftware:masterfrom
oarepo:contribution-same-as-permission
Mar 6, 2026
Merged

feat: SameAs generator#119
max-moser merged 1 commit intoinveniosoftware:masterfrom
oarepo:contribution-same-as-permission

Conversation

@mesemus
Copy link
Contributor

@mesemus mesemus commented Feb 28, 2026

Warning

This is a backward-incompatible change, as users might, in rare cases, rely on the static binding inside the base permission policy.
Please consider merging #120 for the same release as that would need major bump as well

Note

This PR has an accompanying one in invenio-rdm-records - inveniosoftware/invenio-rdm-records#2267
This PR has an accompanying one in invenio-requests - inveniosoftware/invenio-requests#582
This PR has an accompanying one in invenio-communities - inveniosoftware/invenio-communities#1355

Description

A permission policy can be a complicated thing - look for example at the RDM permission policy:

class RDMPermissionPolicy:
    can_manage = [
        RecordOwners(),
        RecordCommunitiesAction("curate"),
        AccessGrant("manage"),
        SystemProcess(),
    ]
    can_curate = can_manage + [AccessGrant("edit"), SecretLinks("edit")]

If we inherit from the policy and modify the can_manage to include another group of users:

class MyPP(RDMPermissionPolicy):
    can_manage = [
        UsersWithRole("myrole"),
        RecordOwners(),
        RecordCommunitiesAction("curate"),
        AccessGrant("manage"),
        SystemProcess(),
    ]

can_curate is not updated as a user might expect. When evaluating permissions, can_curate will not contain the UsersWithRole generator because it was created statically inside the RDMPermissionPolicy class.

The SameAs generator addresses this issue by introducing dynamic binding — the delegation/inclusion happens at permission evaluation time. If the RDM policy were defined as follows:

class RDMPermissionPolicy:
    can_manage = [
        RecordOwners(),
        RecordCommunitiesAction("curate"),
        AccessGrant("manage"),
        SystemProcess(),
    ]
    can_curate = [SameAs("can_manage"), AccessGrant("edit"), SecretLinks("edit")]

the example above would work as the user would intuitively expect.

Note: SameAs is a permission generator, so that it can be included anywhere permission generator might go. To simplify permissions, SameAs can also be used outside lists and combined with other lists:

class RDMPermissionPolicy:
    can_manage = [
        RecordOwners(),
        RecordCommunitiesAction("curate"),
        AccessGrant("manage"),
        SystemProcess(),
    ]
    can_curate = SameAs("can_manage") + [AccessGrant("edit"), SecretLinks("edit")]
    can_delete = SameAs("can_curate")

Checklist

Ticks in all boxes and 🟢 on all GitHub actions status checks are required to merge:

Frontend

Reminder

By using GitHub, you have already agreed to the GitHub’s Terms of Service including that:

  1. You license your contribution under the same terms as the current repository’s license.
  2. You agree that you have the right to license your contribution under the current repository’s license.

@mesemus mesemus force-pushed the contribution-same-as-permission branch 3 times, most recently from 0dbf9f5 to 8c8cd95 Compare February 28, 2026 14:29
@mesemus mesemus force-pushed the contribution-same-as-permission branch 3 times, most recently from 28c9a14 to 4ccd60e Compare March 1, 2026 09:16
Copy link
Contributor

@max-moser max-moser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks amazing, and has the potential to massively simplify permission policy definitions!
thanks a lot for this 😃

i'll take it for a test ride and approve after 🙂

@mesemus mesemus force-pushed the contribution-same-as-permission branch from c3d3ad0 to f057e35 Compare March 1, 2026 16:18
* Changed permission policy's context to
  propagate policy instance to generators
* Added CompositeGenerator class
* Added implementation of SameAs with tests

Co-authored-by: Ronald Krist <ronald.krist@cesnet.cz>
Co-authored-by: Max <maximilian.moser@tuwien.ac.at>
@mesemus mesemus force-pushed the contribution-same-as-permission branch from f057e35 to 44627a4 Compare March 2, 2026 07:51
@max-moser
Copy link
Contributor

FYI, I'm currently in the process of reshaping our own custom permission policy with this new generator, and preliminary results are very promising: https://gitlab.tuwien.ac.at/crdm/invenio-config-tuw/-/merge_requests/110

Copy link
Contributor

@max-moser max-moser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this new permission generator, I was able to cut down our custom TUWRecordPermissionPolicy from 131 lines of code down to 38 (and half of those are comments).
Now we only have 4 explicit action permission definitions left, instead of overriding almost every single one like before.

Massive work, thanks a ton!

Copy link
Member

@zzacharo zzacharo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this!!!!

mesemus added a commit to oarepo/invenio-requests that referenced this pull request Mar 3, 2026
mesemus added a commit to oarepo/invenio-communities that referenced this pull request Mar 3, 2026
mesemus added a commit to oarepo/invenio-communities that referenced this pull request Mar 3, 2026
mesemus added a commit to oarepo/invenio-requests that referenced this pull request Mar 3, 2026
mesemus added a commit to oarepo/invenio-communities that referenced this pull request Mar 3, 2026
@max-moser max-moser merged commit 4836682 into inveniosoftware:master Mar 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants