Skip to content

Commit

Permalink
Merge branch 'master' into ado-6-ndv-simplify-credentials
Browse files Browse the repository at this point in the history
* master:
  fix(core): Fixes event msg confirmations if no subscribers present (#5118)
  refactor(core): Diverge syntax error handling in expressions (#5124)
  fix(editor): Recover from unsaved finished execution  (#5121)
  feat(editor): Executions page (#4997)
  docs: Update the contribution guidelines for node creation (#5120)
  feat: Expression extension framework (#4372)
  fix(editor): Fixes event bus test (#5119)
  refactor(TelegramTrigger Node, ShopifyTrigger Node): Standardize node triggers actions (#5117)
  feat(editor): Remove prevent-ndv-auto-open feature flag (#5114)
  refactor: On workflow deletion, cascade delete all entities associated with it (#5102)

# Conflicts:
#	packages/editor-ui/src/Interface.ts
  • Loading branch information
MiloradFilipovic committed Jan 11, 2023
2 parents 51b4d69 + 62d06b1 commit 18ed51a
Show file tree
Hide file tree
Showing 61 changed files with 3,701 additions and 581 deletions.
28 changes: 28 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest: current file",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["${fileBasenameNoExtension}"],
"console": "integratedTerminal",
"windows": {
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
}
},
{
"name": "Attach to running n8n",
"processId": "${command:PickProcess}",
"request": "attach",
Expand All @@ -24,6 +35,23 @@
"outputCapture": "std",
"killBehavior": "polite"
},
{
"name": "Launch n8n CLI dev with debug",
"runtimeExecutable": "pnpm",
"cwd": "${workspaceFolder}/packages/cli",
"runtimeArgs": ["run", "dev", "--", "--inspect-brk"],
"console": "integratedTerminal",
"restart": true,
"autoAttachChildProcesses": true,
"request": "launch",
"skipFiles": ["<node_internals>/**"],
"type": "node",
"env": {
// "N8N_PORT": "5679",
},
"outputCapture": "std",
"killBehavior": "polite"
},
{
"name": "Debug CLI tests",
"cwd": "${workspaceFolder}/packages/cli",
Expand Down
14 changes: 1 addition & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,19 +185,7 @@ tests of all packages.

## Create custom nodes

> **IMPORTANT**: Avoid use of external libraries to ensure your custom nodes can be reviewed and merged quickly.
Learn about [using the node dev CLI](https://docs.n8n.io/integrations/creating-nodes/archive/node-developer-cli/) to create custom nodes for n8n.

More information can be found in the documentation of [n8n-node-dev](https://github.com/n8n-io/n8n/tree/master/packages/node-dev), a small CLI which helps with n8n-node-development.

## Create a new node to contribute to n8n

Follow this tutorial on [creating your first node](https://docs.n8n.io/integrations/creating-nodes/build/) for n8n.

## Checklist before submitting a new node

There are several things to keep in mind when creating a node. To help you, we prepared a [checklist](https://docs.n8n.io/integrations/creating-nodes/build/reference/) that covers the requirements for creating nodes, from preparation to submission. This will help us be quicker to review and merge your PR.
Learn about [building nodes](https://docs.n8n.io/integrations/creating-nodes/) to create custom nodes for n8n. You can create community nodes and make them available using [npm](https://www.npmjs.com/).

## Extend documentation

Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/10-settings-log-streaming.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ describe('Log Streaming Settings', () => {
cy.wait(100);
settingsLogStreamingPage.getters.getDestinationModal().should('be.visible');
settingsLogStreamingPage.getters.getSelectDestinationType().click();
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(1).click();
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
settingsLogStreamingPage.getters
.getDestinationNameInput()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import express from 'express';

import { FindConditions, FindManyOptions, In } from 'typeorm';

import * as Db from '@/Db';
import * as ActiveWorkflowRunner from '@/ActiveWorkflowRunner';
import config from '@/config';
import { WorkflowEntity } from '@db/entities/WorkflowEntity';
Expand All @@ -28,6 +27,7 @@ import {
getWorkflowIdsViaTags,
parseTagNames,
} from './workflows.service';
import { WorkflowsService } from '@/workflows/workflows.services';

export = {
createWorkflow: [
Expand Down Expand Up @@ -58,27 +58,16 @@ export = {
deleteWorkflow: [
authorize(['owner', 'member']),
async (req: WorkflowRequest.Get, res: express.Response): Promise<express.Response> => {
const { id } = req.params;

const sharedWorkflow = await getSharedWorkflow(req.user, id);
const { id: workflowId } = req.params;

if (!sharedWorkflow) {
const workflow = await WorkflowsService.delete(req.user, workflowId);
if (!workflow) {
// user trying to access a workflow he does not own
// or workflow does not exist
return res.status(404).json({ message: 'Not Found' });
}

if (sharedWorkflow.workflow.active) {
// 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);
return res.json(workflow);
},
],
getWorkflow: [
Expand Down
Original file line number Diff line number Diff line change
@@ -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);`,
);
}
}
2 changes: 2 additions & 0 deletions packages/cli/src/databases/migrations/mysqldb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { AddWorkflowVersionIdColumn1669739707125 } from './1669739707125-AddWork
import { AddTriggerCountColumn1669823906994 } from './1669823906994-AddTriggerCountColumn';
import { RemoveWorkflowDataLoadedFlag1671726148420 } from './1671726148420-RemoveWorkflowDataLoadedFlag';
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-DeleteExecutionsWithWorkflows';

export const mysqlMigrations = [
InitialMigration1588157391238,
Expand Down Expand Up @@ -60,4 +61,5 @@ export const mysqlMigrations = [
AddTriggerCountColumn1669823906994,
RemoveWorkflowDataLoadedFlag1671726148420,
MessageEventBusDestinations1671535397530,
DeleteExecutionsWithWorkflows1673268682475,
];
Original file line number Diff line number Diff line change
@@ -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`,
);
}
}
2 changes: 2 additions & 0 deletions packages/cli/src/databases/migrations/postgresdb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { AddWorkflowVersionIdColumn1669739707126 } from './1669739707126-AddWork
import { AddTriggerCountColumn1669823906995 } from './1669823906995-AddTriggerCountColumn';
import { RemoveWorkflowDataLoadedFlag1671726148421 } from './1671726148421-RemoveWorkflowDataLoadedFlag';
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-DeleteExecutionsWithWorkflows';

export const postgresMigrations = [
InitialMigration1587669153312,
Expand Down Expand Up @@ -56,4 +57,5 @@ export const postgresMigrations = [
AddTriggerCountColumn1669823906995,
RemoveWorkflowDataLoadedFlag1671726148421,
MessageEventBusDestinations1671535397530,
DeleteExecutionsWithWorkflows1673268682475,
];
Original file line number Diff line number Diff line change
@@ -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');
}
}
2 changes: 2 additions & 0 deletions packages/cli/src/databases/migrations/sqlite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { AddWorkflowVersionIdColumn1669739707124 } from './1669739707124-AddWork
import { AddTriggerCountColumn1669823906993 } from './1669823906993-AddTriggerCountColumn';
import { RemoveWorkflowDataLoadedFlag1671726148419 } from './1671726148419-RemoveWorkflowDataLoadedFlag';
import { MessageEventBusDestinations1671535397530 } from './1671535397530-MessageEventBusDestinations';
import { DeleteExecutionsWithWorkflows1673268682475 } from './1673268682475-DeleteExecutionsWithWorkflows';

const sqliteMigrations = [
InitialMigration1588102412422,
Expand Down Expand Up @@ -54,6 +55,7 @@ const sqliteMigrations = [
WorkflowStatistics1664196174000,
RemoveWorkflowDataLoadedFlag1671726148419,
MessageEventBusDestinations1671535397530,
DeleteExecutionsWithWorkflows1673268682475,
];

export { sqliteMigrations };
6 changes: 6 additions & 0 deletions packages/cli/src/eventbus/EventMessageClasses/Helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { EventMessageGeneric, EventMessageGenericOptions } from './EventMessageG
import type { AbstractEventMessageOptions } from './AbstractEventMessageOptions';
import { EventMessageWorkflow, EventMessageWorkflowOptions } from './EventMessageWorkflow';
import { EventMessageTypeNames } from 'n8n-workflow';
import { EventMessageAudit, EventMessageAuditOptions } from './EventMessageAudit';
import { EventMessageNode, EventMessageNodeOptions } from './EventMessageNode';

export const getEventMessageObjectByType = (
message: AbstractEventMessageOptions,
Expand All @@ -12,6 +14,10 @@ export const getEventMessageObjectByType = (
return new EventMessageGeneric(message as EventMessageGenericOptions);
case EventMessageTypeNames.workflow:
return new EventMessageWorkflow(message as EventMessageWorkflowOptions);
case EventMessageTypeNames.audit:
return new EventMessageAudit(message as EventMessageAuditOptions);
case EventMessageTypeNames.node:
return new EventMessageNode(message as EventMessageNodeOptions);
default:
return null;
}
Expand Down
Loading

0 comments on commit 18ed51a

Please sign in to comment.