Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ import { DeployedProcessInfo } from '@/lib/engines/deployment';
import StartFormModal from './start-form-modal';
import useInstanceVariables from './use-instance-variables';
import { inlineScript, inlineUserTaskData } from '@proceed/user-task-helper';
import { getGlobalVariablesForHTML } from '@/lib/engines/server-actions';
import { useEnvironment } from '@/components/auth-can';
import { useSession } from 'next-auth/react';
import { isUserErrorResponse } from '@/lib/user-error';

export default function ProcessDeploymentView({
processId,
Expand All @@ -56,6 +60,9 @@ export default function ProcessDeploymentView({
const canvasRef = useRef<BPMNCanvasRef>(null);
const [infoPanelOpen, setInfoPanelOpen] = useState(false);

const { spaceId } = useEnvironment();
const { data: session } = useSession();

const {
data: deploymentInfo,
refetch,
Expand Down Expand Up @@ -199,8 +206,21 @@ export default function ProcessDeploymentView({
.filter((variable) => variable.value !== undefined)
.map((variable) => [variable.name, variable.value]),
);

if (!session) throw new Error('Unknown user tries to start an instance!');

const globalVars = await getGlobalVariablesForHTML(
spaceId,
session.user.id,
startForm,
);

startForm = inlineScript(startForm, '', '', variableDefinitions);
startForm = inlineUserTaskData(startForm, mappedVariables, []);
startForm = inlineUserTaskData(
startForm,
{ ...mappedVariables, ...globalVars },
[],
);

setStartForm(startForm);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,14 @@ function useDeployment(definitionId: string, initialData?: DeployedProcessInfo)
});

const startInstance = async (versionId: string, variables: { [key: string]: any } = {}) => {
if (engines?.length)
// TODO: in case of static deployment or different versions on different engines we will have
// to check if the engine can actually be used to start an instance
return await startInstanceOnMachine(definitionId, versionId, engines[0], variables, {
processInitiator: session?.user.id,
spaceIdOfProcessInitiator: space.spaceId,
});
if (!engines?.length) return userError('No fitting engine found');

// TODO: in case of static deployment or different versions on different engines we will have
// to check if the engine can actually be used to start an instance
return await startInstanceOnMachine(definitionId, versionId, engines[0], variables, {
processInitiator: session?.user.id,
spaceIdOfProcessInitiator: space.spaceId,
});
};

const activeStates = ['PAUSED', 'RUNNING', 'READY', 'DEPLOYMENT-WAITING', 'WAITING'];
Expand Down Expand Up @@ -170,7 +171,8 @@ function useDeployment(definitionId: string, initialData?: DeployedProcessInfo)
}

async function getStartForm(versionId: string) {
if (!engines) return;
if (!engines?.length) return userError('No fitting engine found');

try {
// TODO: in case of static deployment or different versions on different engines we will have
// to check if the engine can actually be used to start an instance
Expand Down
3 changes: 3 additions & 0 deletions src/management-system-v2/lib/engines/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@ export type InstanceInfo = {
adaptationLog: any[];
processVersion: string;
userTasks: any[];
managementSystemLocation?: string;
processInitiator?: string;
spaceIdOfProcessInitiator?: string;
};
export type DeployedProcessInfo = {
definitionId: string;
Expand Down
65 changes: 60 additions & 5 deletions src/management-system-v2/lib/engines/server-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from './deployment';
import { Engine, SpaceEngine } from './machines';
import { savedEnginesToEngines } from './saved-engines-helpers';
import { getCurrentEnvironment } from '@/components/auth';
import { getCurrentEnvironment, getCurrentUser } from '@/components/auth';
import { enableUseDB } from 'FeatureFlags';
import { getDbEngines, getDbEngineByAddress } from '@/lib/data/db/engines';
import { asyncFilter, asyncMap, asyncForEach } from '../helpers/javascriptHelpers';
Expand All @@ -34,6 +34,7 @@ import {
getCorrectVariableState,
getCorrectMilestoneState,
inlineScript,
getGlobalVariables,
} from '@proceed/user-task-helper';
import { ExtendedTaskListEntry, UserTask } from '../user-task-schema';

Expand All @@ -49,6 +50,7 @@ import { getProcessIds, getVariablesFromElementById } from '@proceed/bpmn-helper
import { Variable } from '@proceed/bpmn-helper/src/getters';
import Ability from '../ability/abilityHelper';
import { getUserById } from '../data/db/iam/users';
import { getDataObject, isErrorResponse } from '@/app/api/spaces/[spaceId]/data/helper';

export async function getCorrectTargetEngines(
spaceId: string,
Expand Down Expand Up @@ -299,9 +301,11 @@ export async function getAvailableTaskListEntries(spaceId: string, engines: Engi
username?: string | null;
firstName?: string | null;
lastName?: string | null;
}[] = await asyncMap(task.actualOwner, async (owner) => {
return getUserById(owner, undefined, tx) || owner;
});
}[] = (
await asyncMap(task.actualOwner, async (owner) => {
return getUserById(owner, undefined, tx) || owner;
})
).filter(truthyFilter);

return users.map((user) =>
typeof user === 'string'
Expand All @@ -321,6 +325,38 @@ export async function getAvailableTaskListEntries(spaceId: string, engines: Engi
}
}

export async function getGlobalVariablesForHTML(
spaceId: string,
initiatorId: string,
html: string,
) {
return await getGlobalVariables(html, async (varPath) => {
let segments = varPath.split('.');

let userId: string | undefined;

if (segments[0] === '@process-initiator') {
userId = initiatorId;
} else if (segments[0] === '@worker' || !segments[0].startsWith('@')) {
({ userId } = await getCurrentUser());
} else if (segments[0] !== '@organization') {
throw new UserFacingError(
`Invalid selector for global data access in user task html. (${segments[0]})`,
);
}

if (segments[0].startsWith('@')) segments = segments.slice(1);

const result = await getDataObject(spaceId, segments.join('.'), userId);

if (isErrorResponse(result)) {
throw new UserFacingError(await result.data.text());
}

return result.data?.value;
});
}

export async function getTasklistEntryHTML(
spaceId: string,
userTaskId: string,
Expand Down Expand Up @@ -348,6 +384,7 @@ export async function getTasklistEntryHTML(

if (engine && (!html || !milestones || !initialVariables)) {
const [taskId, instanceId, startTimeString] = userTaskId.split('|');

const [definitionId] = instanceId.split('-_');

const startTime = parseInt(startTimeString);
Expand All @@ -371,10 +408,11 @@ export async function getTasklistEntryHTML(

initialVariables = getCorrectVariableState(userTask, instance);
milestones = await getCorrectMilestoneState(version.bpmn, userTask, instance);
variableChanges = initialVariables;

html = await getUserTaskFileFromMachine(engine, definitionId, filename);

variableChanges = initialVariables;

html = html.replace(/\/resources\/process[^"]*/g, (match) => {
const path = match.split('/');
return `/api/private/${spaceId}/engine/resources/process/${definitionId}/images/${path.pop()}`;
Expand Down Expand Up @@ -430,6 +468,23 @@ export async function getTasklistEntryHTML(
if (!html) throw new Error('Failed to get the html for the user task');
if (!milestones) throw new Error('Failed to get the milestones for the user task');

let globalVars: Record<string, any> = {};

if (storedUserTask.instanceID) {
if (!engine) throw new Error('Cannot retrieve the instance initiator information.');
const [definitionId] = storedUserTask.instanceID.split('-_');
const deployment = await fetchDeployment(engine, definitionId);
const instance = deployment.instances.find(
(i) => i.processInstanceId === storedUserTask.instanceID,
);
if (!instance) throw new Error('Unknown instance');
if (!instance.processInitiator) throw new Error('Missing initiator information');

globalVars = await getGlobalVariablesForHTML(spaceId, instance.processInitiator, html);
}

variableChanges = { ...variableChanges, ...globalVars };

return inlineUserTaskData(html, mapResourceUrls(variableChanges), milestones);
} catch (e) {
const message = getErrorMessage(e);
Expand Down
Loading