예제 #1
0
    def _get_workflow_as_clientside_update(self) -> WorkflowUpdateData:
        """Return (clientside.Update, delta_id).

        Raise Workflow.DoesNotExist if a race deletes the Workflow.
        """
        with self._lookup_requested_workflow_with_auth_and_cooperative_lock(
        ) as workflow:
            if self.scope["user"].is_anonymous:
                user = None
            else:
                user_id = self.scope["user"].id
                lock_user_by_id(user_id, for_write=False)
                user = query_clientside_user(user_id)

            update = clientside.Update(
                user=user,
                workflow=workflow.to_clientside(),
                tabs={
                    tab.slug: tab.to_clientside()
                    for tab in workflow.live_tabs
                },
                steps={
                    step.id: step.to_clientside()
                    for step in Step.live_in_workflow(workflow)
                },
            )
            return WorkflowUpdateData(update, workflow.last_delta_id)
예제 #2
0
def locked_and_loaded_step(
    workflow_id: int, step_slug: str
) -> ContextManager[Tuple[DbObjectCooperativeLock, Step, str]]:
    """Yield `WorkflowLock`, `step` and `file_param_id_name`.

    SECURITY: the caller may want to test the Step's `file_upload_api_token`.

    Raise UploadError(404, "workflow-not-found") on missing/deleted Workflow.

    Raise UploadError(404, "step-not-found") on missing/deleted Step.

    Raise UploadError(400, "step-module-deleted") on code-less Step.

    Raise UploadError(400, "step-has-no-file-param") on a Step with no File param.
    """
    try:
        with Workflow.lookup_and_cooperative_lock(
                id=workflow_id) as workflow_lock:
            workflow = workflow_lock.workflow
            try:
                step = Step.live_in_workflow(workflow).get(slug=step_slug)
            except Step.DoesNotExist:
                raise UploadError(404, "step-not-found")

            try:
                module_zipfile = MODULE_REGISTRY.latest(step.module_id_name)
            except KeyError:
                raise UploadError(400, "step-module-deleted")

            try:
                file_param_id_name = next(
                    iter(pf.id_name
                         for pf in module_zipfile.get_spec().param_fields
                         if pf.type == "file"))
            except StopIteration:
                raise UploadError(400, "step-has-no-file-param")

            yield workflow_lock, step, file_param_id_name
    except Workflow.DoesNotExist:
        raise UploadError(404, "workflow-not-found")
예제 #3
0
def _load_step_by_slug_sync(workflow: Workflow, step_slug: str) -> Step:
    """Return a Step or raise HandlerError."""
    try:
        return Step.live_in_workflow(workflow).get(slug=step_slug)
    except Step.DoesNotExist:
        raise HandlerError("DoesNotExist: Step not found")
예제 #4
0
def _load_step_by_id(workflow: Workflow, step_id: int) -> Step:
    """Return a Step or raises HandlerError."""
    try:
        return Step.live_in_workflow(workflow).get(id=step_id)
    except Step.DoesNotExist:
        raise HandlerError("DoesNotExist: Step not found")
예제 #5
0
def _workflow_has_notifications(workflow_id: int) -> bool:
    """Detect whether a workflow sends email on changes."""
    return Step.live_in_workflow(workflow_id).filter(
        notifications=True).exists()