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:
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.
| Argument | Description |
|---|---|
permission_policy | The policy class, a subclass of invenio_records_permissions.policies.records.RecordPermissionPolicy |
keep_mixins | By 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:
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:
| Generator | Import | Description |
|---|---|---|
AnyUser() | invenio_records_permissions.generators | Any user, including anonymous users |
AuthenticatedUser() | invenio_records_permissions.generators | Any authenticated user |
SystemProcess() | invenio_records_permissions.generators | The system process or a superuser |
SystemProcessWithoutSuperUser() | invenio_records_permissions.generators | Only the system process |
AnyUserIfPublic() | invenio_records_permissions.generators | Any user if the record is public |
RecordOwners() | invenio_rdm_records.services.generators | Owner 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):
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")].