Пример #1
0
def lock_workflow_for_role(
    workflow: Workflow, scope: Dict[str, Any], role: Literal["read", "write", "owner"]
) -> ContextManager:
    """Update Workflow, authenticate and yield; or raise HandlerError.

    Raise HandlerError if workflow does not exist.

    Raise HandlerError if request scope is not allowed role.

    This must be called in synchronous database code. The yielded block will
    run within a transaction in which `workflow` is guaranteed not to be
    written by any other processes.
    """
    with transaction.atomic():
        try:
            # Lock the workflow, in the database.
            # This will block until the workflow is released.
            # https://docs.djangoproject.com/en/2.0/ref/models/querysets/#select-for-update
            #
            # list() executes the query
            list(Workflow.objects.select_for_update().filter(id=workflow.id))
        except Workflow.DoesNotExist:
            raise HandlerError("Workflow.DoesNotExist")
        # save() overwrites all fields, so make sure we have the latest
        # versions.
        # https://code.djangoproject.com/ticket/28344#comment:10
        workflow.refresh_from_db()  # won't fail: we're locked

        if not is_workflow_authorized(workflow, scope, role):
            raise HandlerError("AuthError: no %s access to workflow" % (role,))

        yield
def be_paranoid_and_assert_commands_apply(workflow: Workflow) -> None:
    """Run some excessive tests.

    This made sense [2021-02-02] when we first implemented this feature. But has
    it ever caught an error? It didn't on 2021-02-02 when it was added to every
    test.
    """
    workflow.refresh_from_db()
    name1 = workflow.name
    delta = do(SetWorkflowTitle, workflow.id, new_value="paranoid")
    workflow.refresh_from_db()
    assert workflow.last_delta_id == delta.id
    assert workflow.name == "paranoid"
    undo(workflow.id)
    workflow.refresh_from_db()
    assert workflow.name == name1