Skip to Content

Permissions

Every model has a permission policy: a class that says who can perform which action (search, read, create, publish, upload files, …) on the model’s records, drafts and files. The record service and the file services of the model use this policy.

If your model uses workflows, the permissions are defined per workflow in the workflow’s permission policy. See Create workflow. The rest of this page applies to models that set their permission policy directly.

Default policy

Unless something else sets a policy, the model uses oarepo_runtime.services.config.EveryonePermissionPolicy. This policy lets anyone, including anonymous users, perform every action, so it is only suitable for development.

Always set a permission policy (or use workflows) before exposing the repository to users.

Setting the permission policy easy

Pass the SetPermissionPolicy customization to the model() call in your model’s model.py:

equipment/model.py
from oarepo_model.api import model from oarepo_model.customizations import SetPermissionPolicy from .permissions import EquipmentPermissionPolicy equipment_model = model( "equipment", # ... presets, types, metadata_type etc. as generated for your model customizations=[ SetPermissionPolicy(EquipmentPermissionPolicy), ], )

SetPermissionPolicy(permission_policy, keep_mixins=False) makes permission_policy the base class of the model’s PermissionPolicy class.

ArgumentDescription
permission_policyThe policy class, a subclass of invenio_records_permissions.policies.records.RecordPermissionPolicy
keep_mixinsBy default, mixins that presets or other customizations added to the PermissionPolicy class are removed, so your class is used exactly as written. Set to True to keep them.

Custom permission policy intermediate

To define your own policy, create a class that inherits from invenio_records_permissions.policies.records.RecordPermissionPolicy:

equipment/permissions.py
from invenio_rdm_records.services.generators import RecordOwners from invenio_records_permissions.generators import ( AnyUser, AuthenticatedUser, SystemProcess, ) from invenio_records_permissions.policies.records import RecordPermissionPolicy class EquipmentPermissionPolicy(RecordPermissionPolicy): """Anyone can read, authenticated users can deposit, owners can edit.""" can_search = [SystemProcess(), AnyUser()] can_read = [SystemProcess(), AnyUser()] can_create = [SystemProcess(), AuthenticatedUser()] can_update = [SystemProcess(), RecordOwners()] can_delete = [SystemProcess()] can_manage = [SystemProcess(), RecordOwners()] can_create_files = [SystemProcess(), RecordOwners()] can_set_content_files = [SystemProcess(), RecordOwners()] can_get_content_files = [SystemProcess(), AnyUser()] can_commit_files = [SystemProcess(), RecordOwners()] can_read_files = [SystemProcess(), AnyUser()] can_update_files = [SystemProcess(), RecordOwners()] can_delete_files = [SystemProcess(), RecordOwners()] can_edit = [SystemProcess(), RecordOwners()] can_new_version = [SystemProcess(), RecordOwners()] can_search_drafts = [SystemProcess(), AuthenticatedUser()] can_read_draft = [SystemProcess(), RecordOwners()] can_update_draft = [SystemProcess(), RecordOwners()] can_delete_draft = [SystemProcess(), RecordOwners()] can_publish = [SystemProcess(), RecordOwners()] can_draft_create_files = [SystemProcess(), RecordOwners()] can_draft_set_content_files = [SystemProcess(), RecordOwners()] can_draft_get_content_files = [SystemProcess(), RecordOwners()] can_draft_commit_files = [SystemProcess(), RecordOwners()] can_draft_read_files = [SystemProcess(), RecordOwners()] can_draft_update_files = [SystemProcess(), RecordOwners()]

The names of the attributes are the names of the actions prefixed with can_. An action that neither your class nor RecordPermissionPolicy defines is denied. Note that RecordPermissionPolicy has its own defaults for some actions (e.g., can_search allows anyone), so define every action you rely on explicitly. The values are lists of permission generators; the action is allowed if any of them matches the current user. Commonly used generators:

GeneratorImportDescription
AnyUser()invenio_records_permissions.generatorsAny user, including anonymous users
AuthenticatedUser()invenio_records_permissions.generatorsAny authenticated user
SystemProcess()invenio_records_permissions.generatorsThe system process or a superuser
SystemProcessWithoutSuperUser()invenio_records_permissions.generatorsOnly the system process
AnyUserIfPublic()invenio_records_permissions.generatorsAny user if the record is public
RecordOwners()invenio_rdm_records.services.generatorsOwner of the record (read from parent.access, so the model must be based on the RDM templates)

Include SystemProcess() in every action, otherwise background tasks and command-line tools (such as fixtures loading or reindexing) are denied as well.

Custom permission generators advanced

You can also define your own permission generators. Create a class that inherits from invenio_records_permissions.generators.Generator and provides the needs (who is allowed) and a query filter (which records the user can find in search):

equipment/permissions.py
from flask_principal import RoleNeed from invenio_records_permissions.generators import Generator from invenio_search.engine import dsl class UserWithRole(Generator): """Allows users that have any of the given roles.""" def __init__(self, *roles): self.roles = roles def needs(self, **kwargs): return [RoleNeed(role) for role in self.roles] def query_filter(self, identity=None, **kwargs): if not identity: return dsl.Q("match_none") for provide in identity.provides: if provide.method == "role" and provide.value in self.roles: return dsl.Q("match_all") return dsl.Q("match_none")

Use it in a policy like the built-in generators, e.g. can_create = [SystemProcess(), UserWithRole("uploader")].

Last updated on