Skip to content

Commit 1f842db

Browse files
authored
Merge pull request #730 from PROCEED-Labs/ms/user-task-data-access
MS: User Tasks with Space and User Data Access
2 parents 9436a72 + 365442d commit 1f842db

4 files changed

Lines changed: 94 additions & 14 deletions

File tree

src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/process-deployment-view.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ import { DeployedProcessInfo } from '@/lib/engines/deployment';
3333
import StartFormModal from './start-form-modal';
3434
import useInstanceVariables from './use-instance-variables';
3535
import { inlineScript, inlineUserTaskData } from '@proceed/user-task-helper';
36+
import { getGlobalVariablesForHTML } from '@/lib/engines/server-actions';
37+
import { useEnvironment } from '@/components/auth-can';
38+
import { useSession } from 'next-auth/react';
39+
import { isUserErrorResponse } from '@/lib/user-error';
3640

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

63+
const { spaceId } = useEnvironment();
64+
const { data: session } = useSession();
65+
5966
const {
6067
data: deploymentInfo,
6168
refetch,
@@ -199,8 +206,21 @@ export default function ProcessDeploymentView({
199206
.filter((variable) => variable.value !== undefined)
200207
.map((variable) => [variable.name, variable.value]),
201208
);
209+
210+
if (!session) throw new Error('Unknown user tries to start an instance!');
211+
212+
const globalVars = await getGlobalVariablesForHTML(
213+
spaceId,
214+
session.user.id,
215+
startForm,
216+
);
217+
202218
startForm = inlineScript(startForm, '', '', variableDefinitions);
203-
startForm = inlineUserTaskData(startForm, mappedVariables, []);
219+
startForm = inlineUserTaskData(
220+
startForm,
221+
{ ...mappedVariables, ...globalVars },
222+
[],
223+
);
204224

205225
setStartForm(startForm);
206226
} else {

src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/deployment-hook.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,14 @@ function useDeployment(definitionId: string, initialData?: DeployedProcessInfo)
100100
});
101101

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

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

172173
async function getStartForm(versionId: string) {
173-
if (!engines) return;
174+
if (!engines?.length) return userError('No fitting engine found');
175+
174176
try {
175177
// TODO: in case of static deployment or different versions on different engines we will have
176178
// to check if the engine can actually be used to start an instance

src/management-system-v2/lib/engines/deployment.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ export type InstanceInfo = {
313313
adaptationLog: any[];
314314
processVersion: string;
315315
userTasks: any[];
316+
managementSystemLocation?: string;
317+
processInitiator?: string;
318+
spaceIdOfProcessInitiator?: string;
316319
};
317320
export type DeployedProcessInfo = {
318321
definitionId: string;

src/management-system-v2/lib/engines/server-actions.ts

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from './deployment';
1313
import { Engine, SpaceEngine } from './machines';
1414
import { savedEnginesToEngines } from './saved-engines-helpers';
15-
import { getCurrentEnvironment } from '@/components/auth';
15+
import { getCurrentEnvironment, getCurrentUser } from '@/components/auth';
1616
import { enableUseDB } from 'FeatureFlags';
1717
import { getDbEngines, getDbEngineByAddress } from '@/lib/data/db/engines';
1818
import { asyncFilter, asyncMap, asyncForEach } from '../helpers/javascriptHelpers';
@@ -34,6 +34,7 @@ import {
3434
getCorrectVariableState,
3535
getCorrectMilestoneState,
3636
inlineScript,
37+
getGlobalVariables,
3738
} from '@proceed/user-task-helper';
3839
import { ExtendedTaskListEntry, UserTask } from '../user-task-schema';
3940

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

5355
export async function getCorrectTargetEngines(
5456
spaceId: string,
@@ -299,9 +301,11 @@ export async function getAvailableTaskListEntries(spaceId: string, engines: Engi
299301
username?: string | null;
300302
firstName?: string | null;
301303
lastName?: string | null;
302-
}[] = await asyncMap(task.actualOwner, async (owner) => {
303-
return getUserById(owner, undefined, tx) || owner;
304-
});
304+
}[] = (
305+
await asyncMap(task.actualOwner, async (owner) => {
306+
return getUserById(owner, undefined, tx) || owner;
307+
})
308+
).filter(truthyFilter);
305309

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

328+
export async function getGlobalVariablesForHTML(
329+
spaceId: string,
330+
initiatorId: string,
331+
html: string,
332+
) {
333+
return await getGlobalVariables(html, async (varPath) => {
334+
let segments = varPath.split('.');
335+
336+
let userId: string | undefined;
337+
338+
if (segments[0] === '@process-initiator') {
339+
userId = initiatorId;
340+
} else if (segments[0] === '@worker' || !segments[0].startsWith('@')) {
341+
({ userId } = await getCurrentUser());
342+
} else if (segments[0] !== '@organization') {
343+
throw new UserFacingError(
344+
`Invalid selector for global data access in user task html. (${segments[0]})`,
345+
);
346+
}
347+
348+
if (segments[0].startsWith('@')) segments = segments.slice(1);
349+
350+
const result = await getDataObject(spaceId, segments.join('.'), userId);
351+
352+
if (isErrorResponse(result)) {
353+
throw new UserFacingError(await result.data.text());
354+
}
355+
356+
return result.data?.value;
357+
});
358+
}
359+
324360
export async function getTasklistEntryHTML(
325361
spaceId: string,
326362
userTaskId: string,
@@ -348,6 +384,7 @@ export async function getTasklistEntryHTML(
348384

349385
if (engine && (!html || !milestones || !initialVariables)) {
350386
const [taskId, instanceId, startTimeString] = userTaskId.split('|');
387+
351388
const [definitionId] = instanceId.split('-_');
352389

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

372409
initialVariables = getCorrectVariableState(userTask, instance);
373410
milestones = await getCorrectMilestoneState(version.bpmn, userTask, instance);
374-
variableChanges = initialVariables;
375411

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

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

471+
let globalVars: Record<string, any> = {};
472+
473+
if (storedUserTask.instanceID) {
474+
if (!engine) throw new Error('Cannot retrieve the instance initiator information.');
475+
const [definitionId] = storedUserTask.instanceID.split('-_');
476+
const deployment = await fetchDeployment(engine, definitionId);
477+
const instance = deployment.instances.find(
478+
(i) => i.processInstanceId === storedUserTask.instanceID,
479+
);
480+
if (!instance) throw new Error('Unknown instance');
481+
if (!instance.processInitiator) throw new Error('Missing initiator information');
482+
483+
globalVars = await getGlobalVariablesForHTML(spaceId, instance.processInitiator, html);
484+
}
485+
486+
variableChanges = { ...variableChanges, ...globalVars };
487+
433488
return inlineUserTaskData(html, mapResourceUrls(variableChanges), milestones);
434489
} catch (e) {
435490
const message = getErrorMessage(e);

0 commit comments

Comments
 (0)