mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor: On workflow deletion, cascade delete all entities associated with it (#5102)
This commit is contained in:
parent
7df0728999
commit
0e955760a1
|
@ -2,7 +2,6 @@ import express from 'express';
|
||||||
|
|
||||||
import { FindConditions, FindManyOptions, In } from 'typeorm';
|
import { FindConditions, FindManyOptions, In } from 'typeorm';
|
||||||
|
|
||||||
import * as Db from '@/Db';
|
|
||||||
import * as ActiveWorkflowRunner from '@/ActiveWorkflowRunner';
|
import * as ActiveWorkflowRunner from '@/ActiveWorkflowRunner';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
import { WorkflowEntity } from '@db/entities/WorkflowEntity';
|
||||||
|
@ -28,6 +27,7 @@ import {
|
||||||
getWorkflowIdsViaTags,
|
getWorkflowIdsViaTags,
|
||||||
parseTagNames,
|
parseTagNames,
|
||||||
} from './workflows.service';
|
} from './workflows.service';
|
||||||
|
import { WorkflowsService } from '@/workflows/workflows.services';
|
||||||
|
|
||||||
export = {
|
export = {
|
||||||
createWorkflow: [
|
createWorkflow: [
|
||||||
|
@ -58,27 +58,16 @@ export = {
|
||||||
deleteWorkflow: [
|
deleteWorkflow: [
|
||||||
authorize(['owner', 'member']),
|
authorize(['owner', 'member']),
|
||||||
async (req: WorkflowRequest.Get, res: express.Response): Promise<express.Response> => {
|
async (req: WorkflowRequest.Get, res: express.Response): Promise<express.Response> => {
|
||||||
const { id } = req.params;
|
const { id: workflowId } = req.params;
|
||||||
|
|
||||||
const sharedWorkflow = await getSharedWorkflow(req.user, id);
|
const workflow = await WorkflowsService.delete(req.user, workflowId);
|
||||||
|
if (!workflow) {
|
||||||
if (!sharedWorkflow) {
|
|
||||||
// user trying to access a workflow he does not own
|
// user trying to access a workflow he does not own
|
||||||
// or workflow does not exist
|
// or workflow does not exist
|
||||||
return res.status(404).json({ message: 'Not Found' });
|
return res.status(404).json({ message: 'Not Found' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sharedWorkflow.workflow.active) {
|
return res.json(workflow);
|
||||||
// deactivate before deleting
|
|
||||||
await ActiveWorkflowRunner.getInstance().remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Db.collections.Workflow.delete(id);
|
|
||||||
|
|
||||||
void InternalHooksManager.getInstance().onWorkflowDeleted(req.user, id, true);
|
|
||||||
await ExternalHooks().run('workflow.afterDelete', [id]);
|
|
||||||
|
|
||||||
return res.json(sharedWorkflow.workflow);
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
getWorkflow: [
|
getWorkflow: [
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
import { logMigrationEnd, logMigrationStart } from '@db/utils/migrationHelpers';
|
||||||
|
import config from '@/config';
|
||||||
|
|
||||||
|
export class DeleteExecutionsWithWorkflows1673268682475 implements MigrationInterface {
|
||||||
|
name = 'DeleteExecutionsWithWorkflows1673268682475';
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
logMigrationStart(this.name);
|
||||||
|
const tablePrefix = config.getEnv('database.tablePrefix');
|
||||||
|
|
||||||
|
await queryRunner.query(`ALTER TABLE \`${tablePrefix}execution_entity\` MODIFY workflowId INT`);
|
||||||
|
|
||||||
|
const workflowIds: Array<{ id: number }> = await queryRunner.query(`
|
||||||
|
SELECT id FROM \`${tablePrefix}execution_entity\`
|
||||||
|
`);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`DELETE FROM \`${tablePrefix}execution_entity\`
|
||||||
|
WHERE workflowId IS NOT NULL
|
||||||
|
${workflowIds.length ? `AND workflowId NOT IN (${workflowIds.map(({ id }) => id).join()})` : ''}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`${tablePrefix}execution_entity\`
|
||||||
|
ADD CONSTRAINT \`FK_${tablePrefix}execution_entity_workflowId\`
|
||||||
|
FOREIGN KEY (\`workflowId\`) REFERENCES \`${tablePrefix}workflow_entity\`(\`id\`)
|
||||||
|
ON DELETE CASCADE`,
|
||||||
|
);
|
||||||
|
|
||||||
|
logMigrationEnd(this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const tablePrefix = config.getEnv('database.tablePrefix');
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`${tablePrefix}execution_entity\`
|
||||||
|
DROP FOREIGN KEY \`FK_${tablePrefix}execution_entity_workflowId\``,
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`${tablePrefix}execution_entity\` MODIFY workflowId varchar(255);`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import { AddWorkflowVersionIdColumn1669739707125 } from './1669739707125-AddWork
|
||||||
import { AddTriggerCountColumn1669823906994 } from './1669823906994-AddTriggerCountColumn';
|
import { AddTriggerCountColumn1669823906994 } from './1669823906994-AddTriggerCountColumn';
|
||||||
import { RemoveWorkflowDataLoadedFlag1671726148420 } from './1671726148420-RemoveWorkflowDataLoadedFlag';
|
import { RemoveWorkflowDataLoadedFlag1671726148420 } from './1671726148420-RemoveWorkflowDataLoadedFlag';
|
||||||
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
|
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
|
||||||
|
import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-DeleteExecutionsWithWorkflows';
|
||||||
|
|
||||||
export const mysqlMigrations = [
|
export const mysqlMigrations = [
|
||||||
InitialMigration1588157391238,
|
InitialMigration1588157391238,
|
||||||
|
@ -60,4 +61,5 @@ export const mysqlMigrations = [
|
||||||
AddTriggerCountColumn1669823906994,
|
AddTriggerCountColumn1669823906994,
|
||||||
RemoveWorkflowDataLoadedFlag1671726148420,
|
RemoveWorkflowDataLoadedFlag1671726148420,
|
||||||
MessageEventBusDestinations1671535397530,
|
MessageEventBusDestinations1671535397530,
|
||||||
|
DeleteExecutionsWithWorkflows1673268682475,
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
import { logMigrationEnd, logMigrationStart } from '@db/utils/migrationHelpers';
|
||||||
|
import config from '@/config';
|
||||||
|
|
||||||
|
export class DeleteExecutionsWithWorkflows1673268682475 implements MigrationInterface {
|
||||||
|
name = 'DeleteExecutionsWithWorkflows1673268682475';
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
logMigrationStart(this.name);
|
||||||
|
const tablePrefix = config.getEnv('database.tablePrefix');
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE ${tablePrefix}execution_entity
|
||||||
|
ALTER COLUMN "workflowId" TYPE INTEGER USING "workflowId"::integer`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const workflowIds: Array<{ id: number }> = await queryRunner.query(`
|
||||||
|
SELECT id FROM ${tablePrefix}workflow_entity
|
||||||
|
`);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`DELETE FROM ${tablePrefix}execution_entity
|
||||||
|
WHERE "workflowId" IS NOT NULL
|
||||||
|
${
|
||||||
|
workflowIds.length
|
||||||
|
? `AND "workflowId" NOT IN (${workflowIds.map(({ id }) => id).join()})`
|
||||||
|
: ''
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE ${tablePrefix}execution_entity
|
||||||
|
ADD CONSTRAINT "FK_${tablePrefix}execution_entity_workflowId"
|
||||||
|
FOREIGN KEY ("workflowId") REFERENCES ${tablePrefix}workflow_entity ("id")
|
||||||
|
ON DELETE CASCADE`,
|
||||||
|
);
|
||||||
|
|
||||||
|
logMigrationEnd(this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const tablePrefix = config.getEnv('database.tablePrefix');
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE ${tablePrefix}execution_entity
|
||||||
|
DROP CONSTRAINT "FK_${tablePrefix}execution_entity_workflowId"`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE ${tablePrefix}execution_entity
|
||||||
|
ALTER COLUMN "workflowId" TYPE TEXT`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import { AddWorkflowVersionIdColumn1669739707126 } from './1669739707126-AddWork
|
||||||
import { AddTriggerCountColumn1669823906995 } from './1669823906995-AddTriggerCountColumn';
|
import { AddTriggerCountColumn1669823906995 } from './1669823906995-AddTriggerCountColumn';
|
||||||
import { RemoveWorkflowDataLoadedFlag1671726148421 } from './1671726148421-RemoveWorkflowDataLoadedFlag';
|
import { RemoveWorkflowDataLoadedFlag1671726148421 } from './1671726148421-RemoveWorkflowDataLoadedFlag';
|
||||||
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
|
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
|
||||||
|
import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-DeleteExecutionsWithWorkflows';
|
||||||
|
|
||||||
export const postgresMigrations = [
|
export const postgresMigrations = [
|
||||||
InitialMigration1587669153312,
|
InitialMigration1587669153312,
|
||||||
|
@ -56,4 +57,5 @@ export const postgresMigrations = [
|
||||||
AddTriggerCountColumn1669823906995,
|
AddTriggerCountColumn1669823906995,
|
||||||
RemoveWorkflowDataLoadedFlag1671726148421,
|
RemoveWorkflowDataLoadedFlag1671726148421,
|
||||||
MessageEventBusDestinations1671535397530,
|
MessageEventBusDestinations1671535397530,
|
||||||
|
DeleteExecutionsWithWorkflows1673268682475,
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
import { logMigrationEnd, logMigrationStart } from '@db/utils/migrationHelpers';
|
||||||
|
import config from '@/config';
|
||||||
|
|
||||||
|
export class DeleteExecutionsWithWorkflows1673268682475 implements MigrationInterface {
|
||||||
|
name = 'DeleteExecutionsWithWorkflows1673268682475';
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
logMigrationStart(this.name);
|
||||||
|
const tablePrefix = config.getEnv('database.tablePrefix');
|
||||||
|
|
||||||
|
const workflowIds: Array<{ id: number }> = await queryRunner.query(`
|
||||||
|
SELECT id FROM "${tablePrefix}workflow_entity"
|
||||||
|
`);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`DELETE FROM "${tablePrefix}execution_entity"
|
||||||
|
WHERE "workflowId" IS NOT NULL
|
||||||
|
${
|
||||||
|
workflowIds.length
|
||||||
|
? `AND "workflowId" NOT IN (${workflowIds.map(({ id }) => id).join()})`
|
||||||
|
: ''
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.query('PRAGMA foreign_keys=OFF');
|
||||||
|
|
||||||
|
await queryRunner.query(`DROP TABLE IF EXISTS "${tablePrefix}temporary_execution_entity"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "${tablePrefix}temporary_execution_entity" (
|
||||||
|
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
"workflowId" int,
|
||||||
|
"finished" boolean NOT NULL,
|
||||||
|
"mode" varchar NOT NULL,
|
||||||
|
"retryOf" varchar,
|
||||||
|
"retrySuccessId" varchar,
|
||||||
|
"startedAt" datetime NOT NULL,
|
||||||
|
"stoppedAt" datetime,
|
||||||
|
"waitTill" datetime,
|
||||||
|
"workflowData" text NOT NULL,
|
||||||
|
"data" text NOT NULL,
|
||||||
|
FOREIGN KEY("workflowId") REFERENCES "${tablePrefix}workflow_entity" ("id") ON DELETE CASCADE
|
||||||
|
)`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const columns =
|
||||||
|
'"id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "workflowData", "data"';
|
||||||
|
await queryRunner.query(
|
||||||
|
`INSERT INTO "${tablePrefix}temporary_execution_entity"(${columns}) SELECT ${columns} FROM "${tablePrefix}execution_entity"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "${tablePrefix}execution_entity"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "${tablePrefix}temporary_execution_entity" RENAME TO "${tablePrefix}execution_entity"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE INDEX "IDX_${tablePrefix}cefb067df2402f6aed0638a6c1" ON "${tablePrefix}execution_entity" ("stoppedAt")`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE INDEX "IDX_${tablePrefix}ca4a71b47f28ac6ea88293a8e2" ON "${tablePrefix}execution_entity" ("waitTill")`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`VACUUM;`);
|
||||||
|
|
||||||
|
await queryRunner.query('PRAGMA foreign_keys=ON');
|
||||||
|
|
||||||
|
logMigrationEnd(this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const tablePrefix = config.getEnv('database.tablePrefix');
|
||||||
|
await queryRunner.query('PRAGMA foreign_keys=OFF');
|
||||||
|
|
||||||
|
await queryRunner.query(`DROP TABLE IF EXISTS "${tablePrefix}temporary_execution_entity"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "${tablePrefix}temporary_execution_entity" (
|
||||||
|
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
"workflowId" varchar,
|
||||||
|
"finished" boolean NOT NULL,
|
||||||
|
"mode" varchar NOT NULL,
|
||||||
|
"retryOf" varchar,
|
||||||
|
"retrySuccessId" varchar,
|
||||||
|
"startedAt" datetime NOT NULL,
|
||||||
|
"stoppedAt" datetime,
|
||||||
|
"waitTill" datetime,
|
||||||
|
"workflowData" text NOT NULL,
|
||||||
|
"data" text NOT NULL
|
||||||
|
)`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const columns =
|
||||||
|
'"id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "workflowData", "data"';
|
||||||
|
await queryRunner.query(
|
||||||
|
`INSERT INTO "${tablePrefix}temporary_execution_entity"(${columns}) SELECT ${columns} FROM "${tablePrefix}execution_entity"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "${tablePrefix}execution_entity"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "${tablePrefix}temporary_execution_entity" RENAME TO "${tablePrefix}execution_entity"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE INDEX "IDX_${tablePrefix}cefb067df2402f6aed0638a6c1" ON "${tablePrefix}execution_entity" ("stoppedAt")`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE INDEX "IDX_${tablePrefix}ca4a71b47f28ac6ea88293a8e2" ON "${tablePrefix}execution_entity" ("waitTill")`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`VACUUM;`);
|
||||||
|
|
||||||
|
await queryRunner.query('PRAGMA foreign_keys=ON');
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import { AddWorkflowVersionIdColumn1669739707124 } from './1669739707124-AddWork
|
||||||
import { AddTriggerCountColumn1669823906993 } from './1669823906993-AddTriggerCountColumn';
|
import { AddTriggerCountColumn1669823906993 } from './1669823906993-AddTriggerCountColumn';
|
||||||
import { RemoveWorkflowDataLoadedFlag1671726148419 } from './1671726148419-RemoveWorkflowDataLoadedFlag';
|
import { RemoveWorkflowDataLoadedFlag1671726148419 } from './1671726148419-RemoveWorkflowDataLoadedFlag';
|
||||||
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
|
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
|
||||||
|
import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-DeleteExecutionsWithWorkflows';
|
||||||
|
|
||||||
const sqliteMigrations = [
|
const sqliteMigrations = [
|
||||||
InitialMigration1588102412422,
|
InitialMigration1588102412422,
|
||||||
|
@ -54,6 +55,7 @@ const sqliteMigrations = [
|
||||||
WorkflowStatistics1664196174000,
|
WorkflowStatistics1664196174000,
|
||||||
RemoveWorkflowDataLoadedFlag1671726148419,
|
RemoveWorkflowDataLoadedFlag1671726148419,
|
||||||
MessageEventBusDestinations1671535397530,
|
MessageEventBusDestinations1671535397530,
|
||||||
|
DeleteExecutionsWithWorkflows1673268682475,
|
||||||
];
|
];
|
||||||
|
|
||||||
export { sqliteMigrations };
|
export { sqliteMigrations };
|
||||||
|
|
|
@ -5,12 +5,11 @@ import { v4 as uuid } from 'uuid';
|
||||||
import { LoggerProxy } from 'n8n-workflow';
|
import { LoggerProxy } from 'n8n-workflow';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import * as ActiveWorkflowRunner from '@/ActiveWorkflowRunner';
|
|
||||||
import * as Db from '@/Db';
|
import * as Db from '@/Db';
|
||||||
import * as GenericHelpers from '@/GenericHelpers';
|
import * as GenericHelpers from '@/GenericHelpers';
|
||||||
import * as ResponseHelper from '@/ResponseHelper';
|
import * as ResponseHelper from '@/ResponseHelper';
|
||||||
import * as WorkflowHelpers from '@/WorkflowHelpers';
|
import * as WorkflowHelpers from '@/WorkflowHelpers';
|
||||||
import { IWorkflowResponse, IExecutionPushResponse } from '@/Interfaces';
|
import type { IWorkflowResponse, IExecutionPushResponse } from '@/Interfaces';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import * as TagHelpers from '@/TagHelpers';
|
import * as TagHelpers from '@/TagHelpers';
|
||||||
import { SharedWorkflow } from '@db/entities/SharedWorkflow';
|
import { SharedWorkflow } from '@db/entities/SharedWorkflow';
|
||||||
|
@ -256,19 +255,8 @@ workflowsController.delete(
|
||||||
ResponseHelper.send(async (req: WorkflowRequest.Delete) => {
|
ResponseHelper.send(async (req: WorkflowRequest.Delete) => {
|
||||||
const { id: workflowId } = req.params;
|
const { id: workflowId } = req.params;
|
||||||
|
|
||||||
await ExternalHooks().run('workflow.delete', [workflowId]);
|
const workflow = await WorkflowsService.delete(req.user, workflowId);
|
||||||
|
if (!workflow) {
|
||||||
const shared = await Db.collections.SharedWorkflow.findOne({
|
|
||||||
relations: ['workflow', 'role'],
|
|
||||||
where: whereClause({
|
|
||||||
user: req.user,
|
|
||||||
entityType: 'workflow',
|
|
||||||
entityId: workflowId,
|
|
||||||
roles: ['owner'],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!shared) {
|
|
||||||
LoggerProxy.verbose('User attempted to delete a workflow without permissions', {
|
LoggerProxy.verbose('User attempted to delete a workflow without permissions', {
|
||||||
workflowId,
|
workflowId,
|
||||||
userId: req.user.id,
|
userId: req.user.id,
|
||||||
|
@ -278,16 +266,6 @@ workflowsController.delete(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shared.workflow.active) {
|
|
||||||
// deactivate before deleting
|
|
||||||
await ActiveWorkflowRunner.getInstance().remove(workflowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Db.collections.Workflow.delete(workflowId);
|
|
||||||
|
|
||||||
void InternalHooksManager.getInstance().onWorkflowDeleted(req.user, workflowId, false);
|
|
||||||
await ExternalHooks().run('workflow.afterDelete', [workflowId]);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
@ -420,4 +420,34 @@ export class WorkflowsService {
|
||||||
executionId,
|
executionId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async delete(user: User, workflowId: string): Promise<WorkflowEntity | undefined> {
|
||||||
|
await ExternalHooks().run('workflow.delete', [workflowId]);
|
||||||
|
|
||||||
|
const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({
|
||||||
|
relations: ['workflow', 'role'],
|
||||||
|
where: whereClause({
|
||||||
|
user,
|
||||||
|
entityType: 'workflow',
|
||||||
|
entityId: workflowId,
|
||||||
|
roles: ['owner'],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!sharedWorkflow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sharedWorkflow.workflow.active) {
|
||||||
|
// deactivate before deleting
|
||||||
|
await ActiveWorkflowRunner.getInstance().remove(workflowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Db.collections.Workflow.delete(workflowId);
|
||||||
|
|
||||||
|
void InternalHooksManager.getInstance().onWorkflowDeleted(user, workflowId, false);
|
||||||
|
await ExternalHooks().run('workflow.afterDelete', [workflowId]);
|
||||||
|
|
||||||
|
return sharedWorkflow.workflow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue