Customize
Record workflows
Configuration example

Configuration example

Repository of measurement data with a workflow for creating, approving, and publishing records.

Roles:

  • researcher (provides files, creates records)
  • supervisor (approves metadata of records)
  • publisher (decides that data should/should not be embargoed and publishes)
  • community member (another researcher within the same community)
  • repository member (another researcher from another community)
  • general audience (anonymous user/any user)
  • curator (owner of the community, responsible for assigning roles within the community)
  • repository administrator (creates communities, assigns community owners)

Workflow:

TODO: obrazek

Configuration

# invenio.cfg
from oarepo_workflows import Workflow
 
WORKFLOWS={
  "default": Workflow(
    label = _('Default workflow'),
    permission_policy_cls =  DefaultWorkflowPermissions,
    request_policy_cls = DefaultWorkflowRequests,
  )
}
# shared/workflows/default/permissions.py
 
class DefaultWorkflowPermissions(WorkflowPermissionPolicy):
    can_create = [
        CommunityRole("editor"),
    ]
 
    can_read = [
        RecordOwners(),
        # curator can see the record in any state
        CommunityRole("curator"),
        # administrator can see everything
        UserWithRole("administrator"),
        # if the record is published and restricted, only members of the community can see it,
        # otherwise, any user can see it
        IfInState(
            "published",
            then_=[
                IfRestricted(
                    "visibility",
                    then_=[CommunityMembers()],
                    else_=[AnyUser()],
                )
            ],
        ),
 
        IfInState("retracting", then_=[RecordOwners(), CommunityRole("curator")]),
    ]
 
    can_update = [
        IfInState(
            "draft",
            then_=[
                RecordOwners(),
                CommunityRole("curator"),
                UserWithRole("administrator"),
            ],
        ),
        # if not draft, can not be directly updated by any means, must use request
    ]
 
    can_delete = [
        # draft can be deleted, published record must be deleted via request
        IfInState(
            "draft",
            then_=[
                RecordOwners(),
                CommunityRole("curator"),
                UserWithRole("administrator"),
            ],
        ),
    ]

Note: SystemProcess() is added automatically to all permissions.

Requests

# shared/workflows/default/requests.py
 
from oarepo_workflows import WorkflowRequestPolicy
from oarepo_workflows.permissions import (
  RecordOwner, SystemProcess, IfInState
)
from oarepo_communities.permissions import CommunityMembers, CommunityRole
 
 
def default_escalation():
    return [
        WorkflowRequestEscalation(
            after=timedelta(days=14), recipients=[UserWithRole("administrator")]
        )
    ]
 
 
class DefaultWorkflowRequests(WorkflowRequestPolicy):
 
    publish_request = WorkflowRequest(
        # if the record is in draft state, the owner or curator can request publishing
        requesters=[
            IfInState("draft", then_=[RecordOwners(), CommunityRole("curator")])
        ],
        recipients=[
            # if the requester is the curator of the community, auto approve the request
            IfRequestedBy(
                CommunityRole("curator"),
                then_=[AutoApprove()],
                else_=[CommunityRole("curator")],
            )
        ],
        transitions=WorkflowTransitions(
            submitted="submitted", accepted="published", declined="draft"
        ),
        # if the request is not resolved in 14 days, escalate it to the administrator
        escalations=default_escalation(),
    )
 
    edit_request = WorkflowRequest(
        requesters=[
            IfInState("published", then_=[RecordOwners(), CommunityRole("curator")])
        ],
        # the request is auto-approve, we do not limit the owner of the record to create a new
        # draft version. It will need to be approved by the curator though.
        recipients=[AutoApprove()],
    )
 
    delete_request = WorkflowRequest(
        # if the record is draft, it is covered by the delete permission
        # if published, only the owner or curator can request deleting
        requesters=[
            IfInState(
                "published",
                then_=[
                    RecordOwners(),
                    CommunityRole("curator"),
                    UserWithRole("administrator"),
                ],
            )
        ],
        # if the requester is the curator of the community, auto approve the request,
        # otherwise, the request is sent to the curator
        recipients=[
            IfRequestedBy(
                CommunityRole("curator"),
                then_=[AutoApprove()],
                else_=[CommunityRole("curator")],
            )
        ],
 
        # the record comes to the state of retracting when the request is submitted. If the request
        # is approved, the record is deleted, if rejected, it is published again.
        transitions=WorkflowTransitions(submitted="retracting", declined="published", accepted="deleted"),
 
        # if the request is not resolved in 14 days, escalate it to the administrator
        escalations=default_escalation(),
    )
 
    assign_doi = WorkflowRequest(
        requesters=[
            RecordOwners(),
            CommunityRole("curator"),
            UserWithRole("administrator"),
        ],
        recipients=[
            IfRequestedBy(
                UserWithRole("administrator"),
                then_=[AutoApprove()],
                else_=[CommunityRole("curator")],
            )
        ],
        escalations=default_escalation(),
    )