feat(core): reimplement blocking workflow updates on interim changes (#4446)
* 📘 Update request type * 📘 Update FE types * ⚡ Adjust store * ⚡ Set received hash * ⚡ Send and load hash * ⚡ Make helper more flexible * 🗃️ Add new field to entity * 🚨 Add check to endpoint * 🧪 Add tests * ⚡ Add `forceSave` flag * 🐛 Fix workflow update failing on new workflow * 🧪 Add more tests * ⚡ Move check to `updateWorkflow()` * ⚡ Refactor to accommodate latest changes * 🧪 Refactor tests to keep them passing * ⚡ Improve syntax
This commit is contained in:
@@ -183,6 +183,7 @@ EEWorkflowController.patch(
|
||||
'/:id(\\d+)',
|
||||
ResponseHelper.send(async (req: WorkflowRequest.Update) => {
|
||||
const { id: workflowId } = req.params;
|
||||
const forceSave = req.query.forceSave === 'true';
|
||||
|
||||
const updateData = new WorkflowEntity();
|
||||
const { tags, ...rest } = req.body;
|
||||
@@ -193,6 +194,7 @@ EEWorkflowController.patch(
|
||||
updateData,
|
||||
workflowId,
|
||||
tags,
|
||||
forceSave,
|
||||
);
|
||||
|
||||
const { id, ...remainder } = updatedWorkflow;
|
||||
|
||||
@@ -121,6 +121,7 @@ export class EEWorkflowsService extends WorkflowsService {
|
||||
workflow: WorkflowEntity,
|
||||
workflowId: string,
|
||||
tags?: string[],
|
||||
forceSave?: boolean,
|
||||
): Promise<WorkflowEntity> {
|
||||
const previousVersion = await EEWorkflowsService.get({ id: parseInt(workflowId, 10) });
|
||||
if (!previousVersion) {
|
||||
@@ -128,13 +129,13 @@ export class EEWorkflowsService extends WorkflowsService {
|
||||
}
|
||||
const allCredentials = await EECredentials.getAll(user);
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
||||
workflow = WorkflowHelpers.validateWorkflowCredentialUsage(
|
||||
workflow,
|
||||
previousVersion,
|
||||
allCredentials,
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw new ResponseHelper.ResponseError(
|
||||
'Invalid workflow credentials - make sure you have access to all credentials and try again.',
|
||||
undefined,
|
||||
@@ -142,6 +143,6 @@ export class EEWorkflowsService extends WorkflowsService {
|
||||
);
|
||||
}
|
||||
|
||||
return super.updateWorkflow(user, workflow, workflowId, tags);
|
||||
return super.updateWorkflow(user, workflow, workflowId, tags, forceSave);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ export class WorkflowsService {
|
||||
workflow: WorkflowEntity,
|
||||
workflowId: string,
|
||||
tags?: string[],
|
||||
forceSave?: boolean,
|
||||
): Promise<WorkflowEntity> {
|
||||
const shared = await Db.collections.SharedWorkflow.findOne({
|
||||
relations: ['workflow'],
|
||||
@@ -74,6 +75,14 @@ export class WorkflowsService {
|
||||
);
|
||||
}
|
||||
|
||||
if (!forceSave && workflow.hash !== shared.workflow.hash) {
|
||||
throw new ResponseHelper.ResponseError(
|
||||
`Workflow ID ${workflowId} cannot be saved because it was changed by another user.`,
|
||||
undefined,
|
||||
400,
|
||||
);
|
||||
}
|
||||
|
||||
// check credentials for old format
|
||||
await WorkflowHelpers.replaceInvalidCredentials(workflow);
|
||||
|
||||
@@ -118,7 +127,9 @@ export class WorkflowsService {
|
||||
await validateEntity(workflow);
|
||||
}
|
||||
|
||||
await Db.collections.Workflow.update(workflowId, workflow);
|
||||
const { hash, ...rest } = workflow;
|
||||
|
||||
await Db.collections.Workflow.update(workflowId, rest);
|
||||
|
||||
if (tags && !config.getEnv('workflowTagsDisabled')) {
|
||||
const tablePrefix = config.getEnv('database.tablePrefix');
|
||||
|
||||
Reference in New Issue
Block a user