Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 87x 87x 87x 87x 87x 87x 87x 87x 87x 87x 87x 87x 87x 87x 87x 1x 1x 78x 78x 78x 78x 78x 78x 78x 78x 78x 78x 78x 78x 78x 78x 78x 16x 16x 62x 62x 1x 1x 13x 13x 13x 13x 13x 4x 4x 13x 2x 2x 13x 2x 2x 5x 5x 13x 13x 13x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { isEmpty } from 'lodash-es';
import { match } from 'ts-pattern';
import { type AuthenticatedContext } from '@amalia/kernel/auth/types';
import {
WorkflowConditionType,
WorkflowStatementStateAction,
type WorkflowCondition,
type WorkflowStatementState,
type WorkflowStep,
} from '@amalia/payout-collaboration/workflows/types';
import { UserRole, type UserContract } from '@amalia/tenants/users/types';
import { defineAbilityFor } from '../abilities';
import { canForceReviewStatements } from '../abilities/statements';
const checkCondition = (
authenticatedContext: AuthenticatedContext,
statementUser: Pick<UserContract, 'id'>,
condition: WorkflowCondition,
): WorkflowStatementStateAction => {
const authorized = match(condition.conditionType)
.with(WorkflowConditionType.OWNER, () => authenticatedContext.user.id === statementUser.id)
.with(
WorkflowConditionType.ROLE,
() => authenticatedContext.user.role === condition.role && statementUser.id !== authenticatedContext.user.id,
)
.with(WorkflowConditionType.USER, () => authenticatedContext.user.id === condition.userId)
.otherwise(() => false);
return authorized ? WorkflowStatementStateAction.NEXT : WorkflowStatementStateAction.UNAUTHORIZED;
};
const canValidStep = (
authenticatedContext: AuthenticatedContext,
statementUser: Pick<UserContract, 'id'>,
step: WorkflowStep,
): WorkflowStatementStateAction => {
const ability = defineAbilityFor(authenticatedContext);
const conditions = step.conditions.map((condition) => checkCondition(authenticatedContext, statementUser, condition));
// Once we computed conditions on current workflow, check if we're already authorized or not
const authorizedAction =
conditions.find((elm) => elm !== WorkflowStatementStateAction.UNAUTHORIZED) ||
WorkflowStatementStateAction.UNAUTHORIZED;
// If we're still unauthorized, but user is an admin and he can skip, then return force
if (authorizedAction === WorkflowStatementStateAction.UNAUTHORIZED && canForceReviewStatements(ability)) {
return WorkflowStatementStateAction.FORCE;
}
return authorizedAction;
};
const canResetSteps = (
authenticatedContext: AuthenticatedContext,
statementUser: UserContract,
reviewed?: boolean,
): WorkflowStatementStateAction => {
if (reviewed && authenticatedContext.user.role !== UserRole.ADMIN) {
return WorkflowStatementStateAction.UNAUTHORIZED;
}
if (authenticatedContext.user.id === statementUser.id) {
return WorkflowStatementStateAction.RESET;
}
if ([UserRole.READ_ONLY_ADMIN, UserRole.READ_ONLY_MANAGER].includes(authenticatedContext.user.role)) {
return WorkflowStatementStateAction.UNAUTHORIZED;
}
const authorized =
authenticatedContext.user.role === UserRole.ADMIN ||
authenticatedContext.hierarchy.isManagerOf(statementUser.id, new Date()); // TODO: Should be at statement date.
return authorized ? WorkflowStatementStateAction.RESET : WorkflowStatementStateAction.UNAUTHORIZED;
};
const getLastValidatedStep = (workflowSteps?: WorkflowStatementState[] | null) =>
!workflowSteps || isEmpty(workflowSteps) ? 0 : (workflowSteps.at(-1)?.to ?? 0);
export const WorkflowUtils = {
canValidStep,
canResetSteps,
getLastValidatedStep,
};
|