Skip to content

Commit

Permalink
Merge branch 'master' into debug-canvas-selection
Browse files Browse the repository at this point in the history
* master: (30 commits)
  🚀 Release 1.14.0 (#7514)
  ci: Fix oclif manifest generation
  feat(Switch Node): Add support for infinite Switch outputs (#7499)
  🚀 Release 1.13.0 (#7512)
  fix(core): Ensure nodes post-processors run in the correct order (#7500)
  feat(editor): Add PH tracking to event (#7511)
  fix(core): Fix workflow activation with history and workflow history for EE (no-changelog) (#7508)
  refactor(core): Make executions pruning more resilient (#7480)
  fix(Spreadsheet File Node): Fix include empty cells not working with v2 (#7505)
  fix(core): Create instance settings directory recursively (no-changelog) (#7506)
  fix(Microsoft SQL Node): Prevent SQL injection (#7467)
  refactor(core): Make pruning via lifecycle configuration in S3 mode mandatory (#7482)
  fix(core): Always derive `instanceId` from the encryption key (no-changlog) (#7501)
  fix(MQTT Trigger Node): Fix node causing a start up hang when active (#7498)
  feat: Collect usage metrics on license renewal (no-changelog) (#7486)
  fix(core): Fix `frontend.settings` external hook execution (#7496)
  fix(Redis Node): Fix adding sets data types (#7444)
  fix: Save new version of the workflow instead of the previous (no-changelog) (#7428)
  refactor(core): Abstract away InstanceSettings and `encryptionKey` into injectable services (no-changelog) (#7471)
  fix(Customer.io Node): Fix api endpoint when using EU region (#7485)
  ...
  • Loading branch information
MiloradFilipovic committed Oct 25, 2023
2 parents f4c1df5 + db4e61b commit 57c8f2a
Show file tree
Hide file tree
Showing 177 changed files with 5,216 additions and 2,341 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ cypress/screenshots/*
cypress/downloads/*
*.swp
CHANGELOG-*.md
packages/cli/oclif.manifest.json
42 changes: 42 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
# [1.14.0](https://github.com/n8n-io/n8n/compare/[email protected]@1.14.0) (2023-10-25)


### Features

* **Switch Node:** Add support for infinite Switch outputs ([#7499](https://github.com/n8n-io/n8n/issues/7499)) ([2febc61](https://github.com/n8n-io/n8n/commit/2febc61ec94928eb196e1b5f815fffa13f8bae07))



# [1.13.0](https://github.com/n8n-io/n8n/compare/[email protected]@1.13.0) (2023-10-25)


### Bug Fixes

* **core:** Always derive `instanceId` from the encryption key (no-changlog) ([#7501](https://github.com/n8n-io/n8n/issues/7501)) ([a9fdd01](https://github.com/n8n-io/n8n/commit/a9fdd018f4f5ba1e11cc10dc3a3b7929a586f818))
* **core:** Do not return `inviteAcceptUrl` in response if email was sent ([#7465](https://github.com/n8n-io/n8n/issues/7465)) ([55c6a1b](https://github.com/n8n-io/n8n/commit/55c6a1b0d394265fa4018a7023971589d8e61b4a))
* **core:** Ensure nodes post-processors run in the correct order ([#7500](https://github.com/n8n-io/n8n/issues/7500)) ([6f45298](https://github.com/n8n-io/n8n/commit/6f45298d3d61b33e762f520129f4775e216707c8)), closes [#7497](https://github.com/n8n-io/n8n/issues/7497)
* **core:** Fix `frontend.settings` external hook execution ([#7496](https://github.com/n8n-io/n8n/issues/7496)) ([774fe20](https://github.com/n8n-io/n8n/commit/774fe202bfde4f2c5cc95f28a33185e261b031a5))
* **core:** Handle gzip and deflate compressed request payloads ([#7461](https://github.com/n8n-io/n8n/issues/7461)) ([83762e0](https://github.com/n8n-io/n8n/commit/83762e051d5e34d9e43caebd6275780da05c6a46))
* **core:** Reduce logging overhead for levels that do not output ([#7479](https://github.com/n8n-io/n8n/issues/7479)) ([76c0481](https://github.com/n8n-io/n8n/commit/76c04815f7f53bf6b4c06bbe5afa52f51f28750d))
* **Customer.io Node:** Fix api endpoint when using EU region ([#7485](https://github.com/n8n-io/n8n/issues/7485)) ([519680c](https://github.com/n8n-io/n8n/commit/519680c2cf37f3b7341e87e71b911ac2fee8bdfa)), closes [#7484](https://github.com/n8n-io/n8n/issues/7484)
* **editor:** Allow importing the same workflow multiple times ([#7458](https://github.com/n8n-io/n8n/issues/7458)) ([3c0a166](https://github.com/n8n-io/n8n/commit/3c0a166f7f1cf225e5d1b4da91f7449f2deed5ca)), closes [#7457](https://github.com/n8n-io/n8n/issues/7457)
* **editor:** Fix canvas selection breaking after interacting with node actions ([#7466](https://github.com/n8n-io/n8n/issues/7466)) ([bc47365](https://github.com/n8n-io/n8n/commit/bc473655fbc09b1172cd6949236ca2871c9d3b8e))
* **editor:** Fix connections disappearing after reactivating canvas and renaming a node ([#7483](https://github.com/n8n-io/n8n/issues/7483)) ([450e0cc](https://github.com/n8n-io/n8n/commit/450e0cc66abbe57697f66835a837e53b5eb883a3))
* **Google Sheets Node:** Append or update runs forever when without column headers ([#7463](https://github.com/n8n-io/n8n/issues/7463)) ([ab6a9bb](https://github.com/n8n-io/n8n/commit/ab6a9bbac29a2caf34f4dd8211cd18116f659804))
* **Microsoft SQL Node:** Prevent SQL injection ([#7467](https://github.com/n8n-io/n8n/issues/7467)) ([a739245](https://github.com/n8n-io/n8n/commit/a7392453323fe06371988fd5bb28d659a7a00cd8))
* **MQTT Trigger Node:** Fix node causing a start up hang when active ([#7498](https://github.com/n8n-io/n8n/issues/7498)) ([baecb93](https://github.com/n8n-io/n8n/commit/baecb93bef30ac00f09b46ea987bb4c9a2fca394))
* **MySQL Node:** Resolve expressions in v1 ([#7464](https://github.com/n8n-io/n8n/issues/7464)) ([5c46bb0](https://github.com/n8n-io/n8n/commit/5c46bb09c137023608119093cabdf896555b22b9))
* **Redis Node:** Fix adding sets data types ([#7444](https://github.com/n8n-io/n8n/issues/7444)) ([4e66023](https://github.com/n8n-io/n8n/commit/4e66023cd428513b76626795c27ba0713c6c4ea9)), closes [#6339](https://github.com/n8n-io/n8n/issues/6339)
* **Spreadsheet File Node:** Fix include empty cells not working with v2 ([#7505](https://github.com/n8n-io/n8n/issues/7505)) ([05e6f2a](https://github.com/n8n-io/n8n/commit/05e6f2a6ac43fb4059e7e6cc40af6c5d75e01c8b)), closes [Ticket#763644](https://github.com/Ticket/issues/763644)


### Features

* **core:** Add support for oauth based service accounts with UM SMTP ([#7311](https://github.com/n8n-io/n8n/issues/7311)) ([647372b](https://github.com/n8n-io/n8n/commit/647372be275c46e9963c96163c9e913a17f13e5f))
* **editor:** Add PH tracking to event ([#7511](https://github.com/n8n-io/n8n/issues/7511)) ([c47d27d](https://github.com/n8n-io/n8n/commit/c47d27dd6da9420add7dad243b2701876f39a95b))
* **Facebook Lead Ads Trigger Node:** Add Facebook Lead Ads Trigger Node ([#7113](https://github.com/n8n-io/n8n/issues/7113)) ([ac814a9](https://github.com/n8n-io/n8n/commit/ac814a9c613f6f9943be8002110ca9e2433918b2))
* **Ghost Node:** Add support for lexical format ([#7488](https://github.com/n8n-io/n8n/issues/7488)) ([7b1973c](https://github.com/n8n-io/n8n/commit/7b1973c058e0cb7dfa436953c6f046c2b3b145eb))
* **RSS Feed Trigger Node:** Add RSS feed trigger node ([#7386](https://github.com/n8n-io/n8n/issues/7386)) ([689360e](https://github.com/n8n-io/n8n/commit/689360ee069043415838f1488486ce8deaef9e38))



# [1.12.0](https://github.com/n8n-io/n8n/compare/[email protected]@1.12.0) (2023-10-18)


Expand Down
42 changes: 31 additions & 11 deletions cypress/e2e/10-undo-redo.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ describe('Undo/Redo', () => {
WorkflowPage.actions.zoomToFit();
WorkflowPage.getters
.canvasNodeByName('Code')
.should('have.attr', 'style', 'left: 860px; top: 220px;');
.should('have.css', 'left', '860px')
.should('have.css', 'top', '220px')

WorkflowPage.actions.hitUndo();
WorkflowPage.getters.canvasNodes().should('have.have.length', 2);
WorkflowPage.getters.nodeConnections().should('have.length', 1);
Expand All @@ -59,7 +61,8 @@ describe('Undo/Redo', () => {
// Last node should be added back to original position
WorkflowPage.getters
.canvasNodeByName('Code')
.should('have.attr', 'style', 'left: 860px; top: 220px;');
.should('have.css', 'left', '860px')
.should('have.css', 'top', '220px')
});

it('should undo/redo deleting node using delete button', () => {
Expand Down Expand Up @@ -133,15 +136,19 @@ describe('Undo/Redo', () => {
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', [50, 150], { clickToFinish: true });
WorkflowPage.getters
.canvasNodeByName('Code')
.should('have.attr', 'style', 'left: 740px; top: 320px;');
.should('have.css', 'left', '740px')
.should('have.css', 'top', '320px')

WorkflowPage.actions.hitUndo();
WorkflowPage.getters
.canvasNodeByName('Code')
.should('have.attr', 'style', 'left: 640px; top: 220px;');
.should('have.css', 'left', '640px')
.should('have.css', 'top', '220px')
WorkflowPage.actions.hitRedo();
WorkflowPage.getters
.canvasNodeByName('Code')
.should('have.attr', 'style', 'left: 740px; top: 320px;');
.should('have.css', 'left', '740px')
.should('have.css', 'top', '320px')
});

it('should undo/redo deleting a connection by pressing delete button', () => {
Expand Down Expand Up @@ -269,8 +276,8 @@ describe('Undo/Redo', () => {
});

it('should undo/redo multiple steps', () => {
const initialPosition = 'left: 420px; top: 220px;';
const movedPosition = 'left: 540px; top: 360px;';
const initialPosition = {left: '420px', top: '220px'};
const movedPosition = {left: '540px', top: '360px'};

WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
Expand All @@ -283,10 +290,17 @@ describe('Undo/Redo', () => {
WorkflowPage.getters.canvasNodes().last().click();
WorkflowPage.actions.hitDisableNodeShortcut();
// Move first one
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', initialPosition);
WorkflowPage.getters.canvasNodes()
.first()
.should('have.css', 'left', initialPosition.left)
.should('have.css', 'top', initialPosition.top)

WorkflowPage.getters.canvasNodes().first().click();
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', [50, 150], { clickToFinish: true });
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', movedPosition);
WorkflowPage.getters.canvasNodes()
.first()
.should('have.css', 'left', movedPosition.left)
.should('have.css', 'top', movedPosition.top)
// Delete the set node
WorkflowPage.getters.canvasNodeByName(EDIT_FIELDS_SET_NODE_NAME).click().click();
cy.get('body').type('{backspace}');
Expand All @@ -297,7 +311,10 @@ describe('Undo/Redo', () => {
WorkflowPage.getters.nodeConnections().should('have.length', 3);
// Second undo: Should move first node to it's original position
WorkflowPage.actions.hitUndo();
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', initialPosition);
WorkflowPage.getters.canvasNodes()
.first()
.should('have.css', 'left', initialPosition.left)
.should('have.css', 'top', initialPosition.top)
// Third undo: Should enable last node
WorkflowPage.actions.hitUndo();
WorkflowPage.getters.disabledNodes().should('have.length', 0);
Expand All @@ -307,7 +324,10 @@ describe('Undo/Redo', () => {
WorkflowPage.getters.disabledNodes().should('have.length', 1);
// Second redo: Should move the first node
WorkflowPage.actions.hitRedo();
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', movedPosition);
WorkflowPage.getters.canvasNodes()
.first()
.should('have.css', 'left', movedPosition.left)
.should('have.css', 'top', movedPosition.top)
// Third redo: Should delete the Set node
WorkflowPage.actions.hitRedo();
WorkflowPage.getters.canvasNodes().should('have.length', 3);
Expand Down
3 changes: 2 additions & 1 deletion cypress/e2e/12-canvas-actions.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ describe('Canvas Actions', () => {
WorkflowPage.getters
.canvasNodes()
.last()
.should('have.attr', 'style', 'left: 860px; top: 220px;');
.should('have.css', 'left', '860px')
.should('have.css', 'top', '220px')
});

it('should delete connections by pressing the delete button', () => {
Expand Down
51 changes: 45 additions & 6 deletions cypress/e2e/12-canvas.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import {
MERGE_NODE_NAME,
} from './../constants';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { NDV, WorkflowExecutionsTab } from '../pages';

const WorkflowPage = new WorkflowPageClass();

const ExecutionsTab = new WorkflowExecutionsTab();
const NDVDialog = new NDV();
const DEFAULT_ZOOM_FACTOR = 1;
const ZOOM_IN_X1_FACTOR = 1.25; // Zoom in factor after one click
const ZOOM_IN_X2_FACTOR = 1.5625; // Zoom in factor after two clicks
Expand All @@ -27,10 +29,15 @@ describe('Canvas Node Manipulation and Navigation', () => {
});

it('should add switch node and test connections', () => {
WorkflowPage.actions.addNodeToCanvas(SWITCH_NODE_NAME, true);
const desiredOutputs = 4;
WorkflowPage.actions.addNodeToCanvas(SWITCH_NODE_NAME, true, true);

for (let i = 0; i < desiredOutputs; i++) {
cy.contains('Add Routing Rule').click()
}

// Switch has 4 output endpoints
for (let i = 0; i < 4; i++) {
NDVDialog.actions.close()
for (let i = 0; i < desiredOutputs; i++) {
WorkflowPage.getters.canvasNodePlusEndpointByName(SWITCH_NODE_NAME, i).click({ force: true });
WorkflowPage.getters.nodeCreatorSearchBar().should('be.visible');
WorkflowPage.actions.addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, false);
Expand All @@ -40,7 +47,7 @@ describe('Canvas Node Manipulation and Navigation', () => {
cy.reload();
cy.waitForLoad();
// Make sure all connections are there after reload
for (let i = 0; i < 4; i++) {
for (let i = 0; i < desiredOutputs; i++) {
const setName = `${EDIT_FIELDS_SET_NODE_NAME}${i > 0 ? i : ''}`;
WorkflowPage.getters
.canvasNodeInputEndpointByName(setName)
Expand Down Expand Up @@ -165,7 +172,8 @@ describe('Canvas Node Manipulation and Navigation', () => {
WorkflowPage.getters
.canvasNodes()
.last()
.should('have.attr', 'style', 'left: 740px; top: 320px;');
.should('have.css', 'left', '740px')
.should('have.css', 'top', '320px')
});

it('should zoom in', () => {
Expand Down Expand Up @@ -306,4 +314,35 @@ describe('Canvas Node Manipulation and Navigation', () => {
WorkflowPage.getters.canvasNodes().should('have.length', 3);
WorkflowPage.getters.nodeConnections().should('have.length', 1);
});

// ADO-1240: Connections would get deleted after activating and deactivating NodeView
it('should preserve connections after rename & node-view switch', () => {
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.actions.executeWorkflow();

ExecutionsTab.actions.switchToExecutionsTab();
ExecutionsTab.getters.successfulExecutionListItems().should('have.length', 1);

ExecutionsTab.actions.switchToEditorTab();

ExecutionsTab.actions.switchToExecutionsTab();
ExecutionsTab.getters.successfulExecutionListItems().should('have.length', 1);

ExecutionsTab.actions.switchToEditorTab();
WorkflowPage.getters.canvasNodes().should('have.length', 2);

WorkflowPage.getters.canvasNodes().last().click();
cy.get('body').trigger('keydown', { key: 'F2' });
cy.get('.rename-prompt').should('be.visible');
cy.get('body').type(RENAME_NODE_NAME);
cy.get('body').type('{enter}');
WorkflowPage.getters.canvasNodeByName(RENAME_NODE_NAME).should('exist');
// Make sure all connections are there after save & reload
WorkflowPage.actions.saveWorkflowOnButtonClick();
cy.reload();
cy.waitForLoad();
WorkflowPage.getters.canvasNodes().should('have.length', 2);
cy.get('.rect-input-endpoint.jtk-endpoint-connected').should('have.length', 1);
})
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "n8n",
"version": "1.12.0",
"version": "1.14.0",
"private": true,
"homepage": "https://n8n.io",
"engines": {
Expand Down
6 changes: 5 additions & 1 deletion packages/cli/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ module.exports = {
},
globalSetup: '<rootDir>/test/setup.ts',
globalTeardown: '<rootDir>/test/teardown.ts',
setupFilesAfterEnv: ['<rootDir>/test/setup-mocks.ts', '<rootDir>/test/extend-expect.ts'],
setupFilesAfterEnv: [
'<rootDir>/test/setup-test-folder.ts',
'<rootDir>/test/setup-mocks.ts',
'<rootDir>/test/extend-expect.ts',
],
coveragePathIgnorePatterns: ['/src/databases/migrations/'],
testTimeout: 10_000,
};
7 changes: 3 additions & 4 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "n8n",
"version": "1.12.0",
"version": "1.14.0",
"description": "n8n Workflow Automation Tool",
"license": "SEE LICENSE IN LICENSE.md",
"homepage": "https://n8n.io",
Expand Down Expand Up @@ -30,7 +30,7 @@
"lint": "eslint . --quiet",
"lintfix": "eslint . --fix",
"postpack": "rm -f oclif.manifest.json",
"prepack": "oclif-dev manifest",
"prepack": "OCLIF_TS_NODE=0 oclif-dev manifest",
"start": "run-script-os",
"start:default": "cd bin && ./n8n",
"start:windows": "cd bin && n8n",
Expand Down Expand Up @@ -99,7 +99,7 @@
},
"dependencies": {
"@n8n/client-oauth2": "workspace:*",
"@n8n_io/license-sdk": "~2.6.1",
"@n8n_io/license-sdk": "~2.7.1",
"@oclif/command": "^1.8.16",
"@oclif/config": "^1.18.17",
"@oclif/core": "^1.16.4",
Expand All @@ -121,7 +121,6 @@
"connect-history-api-fallback": "^1.6.0",
"convict": "^6.2.4",
"cookie-parser": "^1.4.6",
"crypto-js": "~4.1.1",
"csrf": "^3.1.0",
"curlconverter": "3.21.0",
"dotenv": "^8.0.0",
Expand Down
2 changes: 0 additions & 2 deletions packages/cli/src/AbstractServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ export abstract class AbstractServer {

protected endpointWebhookWaiting: string;

protected instanceId = '';

protected webhooksEnabled = true;

protected testWebhooksEnabled = false;
Expand Down
6 changes: 4 additions & 2 deletions packages/cli/src/CrashJournal.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { existsSync } from 'fs';
import { mkdir, utimes, open, rm } from 'fs/promises';
import { join, dirname } from 'path';
import { UserSettings } from 'n8n-core';
import { Container } from 'typedi';
import { InstanceSettings } from 'n8n-core';
import { LoggerProxy, sleep } from 'n8n-workflow';
import { inProduction } from '@/constants';

Expand All @@ -16,7 +17,8 @@ export const touchFile = async (filePath: string): Promise<void> => {
}
};

const journalFile = join(UserSettings.getUserN8nFolderPath(), 'crash.journal');
const { n8nFolder } = Container.get(InstanceSettings);
const journalFile = join(n8nFolder, 'crash.journal');

export const init = async () => {
if (!inProduction) return;
Expand Down
20 changes: 11 additions & 9 deletions packages/cli/src/CredentialsHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */

import { Credentials, NodeExecuteFunctions } from 'n8n-core';
import get from 'lodash/get';

Expand Down Expand Up @@ -53,7 +52,7 @@ import { CredentialTypes } from '@/CredentialTypes';
import { CredentialsOverwrites } from '@/CredentialsOverwrites';
import { whereClause } from './UserManagement/UserManagementHelper';
import { RESPONSE_ERROR_MESSAGES } from './constants';
import { Container } from 'typedi';
import { Service } from 'typedi';
import { isObjectLiteral } from './utils';

const { OAUTH2_CREDENTIAL_TEST_SUCCEEDED, OAUTH2_CREDENTIAL_TEST_FAILED } = RESPONSE_ERROR_MESSAGES;
Expand Down Expand Up @@ -87,12 +86,15 @@ const mockNodeTypes: INodeTypes = {
},
};

@Service()
export class CredentialsHelper extends ICredentialsHelper {
private credentialTypes = Container.get(CredentialTypes);

private nodeTypes = Container.get(NodeTypes);

private credentialsOverwrites = Container.get(CredentialsOverwrites);
constructor(
private readonly credentialTypes: CredentialTypes,
private readonly nodeTypes: NodeTypes,
private readonly credentialsOverwrites: CredentialsOverwrites,
) {
super();
}

/**
* Add the required authentication information to the request
Expand Down Expand Up @@ -349,7 +351,7 @@ export class CredentialsHelper extends ICredentialsHelper {
expressionResolveValues?: ICredentialsExpressionResolveValues,
): Promise<ICredentialDataDecryptedObject> {
const credentials = await this.getCredentials(nodeCredentials, type);
const decryptedDataOriginal = credentials.getData(this.encryptionKey);
const decryptedDataOriginal = credentials.getData();

if (raw === true) {
return decryptedDataOriginal;
Expand Down Expand Up @@ -469,7 +471,7 @@ export class CredentialsHelper extends ICredentialsHelper {
): Promise<void> {
const credentials = await this.getCredentials(nodeCredentials, type);

credentials.setData(data, this.encryptionKey);
credentials.setData(data);
const newCredentialsData = credentials.getDataToSave() as ICredentialsDb;

// Add special database related data
Expand Down
Loading

0 comments on commit 57c8f2a

Please sign in to comment.