n8n 0.167.0 → 0.168.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/execute.js +3 -0
- package/dist/commands/execute.js.map +1 -1
- package/dist/commands/executeBatch.d.ts +2 -0
- package/dist/commands/executeBatch.js +3 -0
- package/dist/commands/executeBatch.js.map +1 -1
- package/dist/commands/import/credentials.d.ts +10 -0
- package/dist/commands/import/credentials.js +87 -26
- package/dist/commands/import/credentials.js.map +1 -1
- package/dist/commands/import/workflow.d.ts +11 -1
- package/dist/commands/import/workflow.js +109 -48
- package/dist/commands/import/workflow.js.map +1 -1
- package/dist/commands/start.js +25 -0
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/user-management/reset.d.ts +7 -0
- package/dist/commands/user-management/reset.js +66 -0
- package/dist/commands/user-management/reset.js.map +1 -0
- package/dist/commands/worker.js +4 -1
- package/dist/commands/worker.js.map +1 -1
- package/dist/config/index.d.ts +23 -0
- package/dist/config/index.js +92 -4
- package/dist/config/index.js.map +1 -1
- package/dist/src/ActiveWorkflowRunner.d.ts +2 -1
- package/dist/src/ActiveWorkflowRunner.js +44 -24
- package/dist/src/ActiveWorkflowRunner.js.map +1 -1
- package/dist/src/CredentialsHelper.d.ts +10 -2
- package/dist/src/CredentialsHelper.js +40 -11
- package/dist/src/CredentialsHelper.js.map +1 -1
- package/dist/src/Db.d.ts +4 -1
- package/dist/src/Db.js +90 -66
- package/dist/src/Db.js.map +1 -1
- package/dist/src/GenericHelpers.d.ts +6 -0
- package/dist/src/GenericHelpers.js +18 -1
- package/dist/src/GenericHelpers.js.map +1 -1
- package/dist/src/Interfaces.d.ts +74 -9
- package/dist/src/InternalHooks.d.ts +42 -6
- package/dist/src/InternalHooks.js +54 -13
- package/dist/src/InternalHooks.js.map +1 -1
- package/dist/src/ResponseHelper.js +5 -0
- package/dist/src/ResponseHelper.js.map +1 -1
- package/dist/src/Server.d.ts +2 -0
- package/dist/src/Server.js +584 -458
- package/dist/src/Server.js.map +1 -1
- package/dist/src/TagHelpers.d.ts +3 -3
- package/dist/src/TagHelpers.js +5 -24
- package/dist/src/TagHelpers.js.map +1 -1
- package/dist/src/UserManagement/Interfaces.d.ts +34 -0
- package/dist/src/UserManagement/Interfaces.js +3 -0
- package/dist/src/UserManagement/Interfaces.js.map +1 -0
- package/dist/src/UserManagement/UserManagementHelper.d.ts +17 -0
- package/dist/src/UserManagement/UserManagementHelper.js +158 -0
- package/dist/src/UserManagement/UserManagementHelper.js.map +1 -0
- package/dist/src/UserManagement/auth/jwt.d.ts +7 -0
- package/dist/src/UserManagement/auth/jwt.js +57 -0
- package/dist/src/UserManagement/auth/jwt.js.map +1 -0
- package/dist/src/UserManagement/email/Interfaces.d.ts +29 -0
- package/dist/src/UserManagement/email/Interfaces.js +3 -0
- package/dist/src/UserManagement/email/Interfaces.js.map +1 -0
- package/dist/src/UserManagement/email/NodeMailer.d.ts +7 -0
- package/dist/src/UserManagement/email/NodeMailer.js +67 -0
- package/dist/src/UserManagement/email/NodeMailer.js.map +1 -0
- package/dist/src/UserManagement/email/UserManagementMailer.d.ts +9 -0
- package/dist/src/UserManagement/email/UserManagementMailer.js +77 -0
- package/dist/src/UserManagement/email/UserManagementMailer.js.map +1 -0
- package/dist/src/UserManagement/email/index.d.ts +2 -0
- package/dist/src/UserManagement/email/index.js +7 -0
- package/dist/src/UserManagement/email/index.js.map +1 -0
- package/dist/src/UserManagement/email/templates/instanceSetup.html +5 -0
- package/dist/src/UserManagement/email/templates/invite.html +4 -0
- package/dist/src/UserManagement/email/templates/passwordReset.html +5 -0
- package/dist/src/UserManagement/index.d.ts +4 -0
- package/dist/src/UserManagement/index.js +6 -0
- package/dist/src/UserManagement/index.js.map +1 -0
- package/dist/src/UserManagement/routes/auth.d.ts +2 -0
- package/dist/src/UserManagement/routes/auth.js +74 -0
- package/dist/src/UserManagement/routes/auth.js.map +1 -0
- package/dist/src/UserManagement/routes/index.d.ts +2 -0
- package/dist/src/UserManagement/routes/index.js +100 -0
- package/dist/src/UserManagement/routes/index.js.map +1 -0
- package/dist/src/UserManagement/routes/me.d.ts +2 -0
- package/dist/src/UserManagement/routes/me.js +85 -0
- package/dist/src/UserManagement/routes/me.js.map +1 -0
- package/dist/src/UserManagement/routes/owner.d.ts +2 -0
- package/dist/src/UserManagement/routes/owner.js +68 -0
- package/dist/src/UserManagement/routes/owner.js.map +1 -0
- package/dist/src/UserManagement/routes/passwordReset.d.ts +2 -0
- package/dist/src/UserManagement/routes/passwordReset.js +129 -0
- package/dist/src/UserManagement/routes/passwordReset.js.map +1 -0
- package/dist/src/UserManagement/routes/users.d.ts +2 -0
- package/dist/src/UserManagement/routes/users.js +334 -0
- package/dist/src/UserManagement/routes/users.js.map +1 -0
- package/dist/src/WaitTracker.js +6 -0
- package/dist/src/WaitTracker.js.map +1 -1
- package/dist/src/WaitingWebhooks.js +9 -1
- package/dist/src/WaitingWebhooks.js.map +1 -1
- package/dist/src/WebhookHelpers.js +17 -1
- package/dist/src/WebhookHelpers.js.map +1 -1
- package/dist/src/WorkflowExecuteAdditionalData.d.ts +3 -3
- package/dist/src/WorkflowExecuteAdditionalData.js +41 -13
- package/dist/src/WorkflowExecuteAdditionalData.js.map +1 -1
- package/dist/src/WorkflowHelpers.d.ts +9 -10
- package/dist/src/WorkflowHelpers.js +48 -17
- package/dist/src/WorkflowHelpers.js.map +1 -1
- package/dist/src/WorkflowRunner.js +4 -2
- package/dist/src/WorkflowRunner.js.map +1 -1
- package/dist/src/WorkflowRunnerProcess.js +7 -4
- package/dist/src/WorkflowRunnerProcess.js.map +1 -1
- package/dist/src/api/credentials.api.d.ts +1 -0
- package/dist/src/api/credentials.api.js +222 -0
- package/dist/src/api/credentials.api.js.map +1 -0
- package/dist/src/constants.d.ts +5 -0
- package/dist/src/constants.js +9 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/databases/entities/CredentialsEntity.d.ts +2 -0
- package/dist/src/databases/entities/CredentialsEntity.js +13 -2
- package/dist/src/databases/entities/CredentialsEntity.js.map +1 -1
- package/dist/src/databases/entities/Role.d.ts +16 -0
- package/dist/src/databases/entities/Role.js +87 -0
- package/dist/src/databases/entities/Role.js.map +1 -0
- package/dist/src/databases/entities/Settings.d.ts +6 -0
- package/dist/src/databases/entities/Settings.js +32 -0
- package/dist/src/databases/entities/Settings.js.map +1 -0
- package/dist/src/databases/entities/SharedCredentials.d.ts +13 -0
- package/dist/src/databases/entities/SharedCredentials.js +83 -0
- package/dist/src/databases/entities/SharedCredentials.js.map +1 -0
- package/dist/src/databases/entities/SharedWorkflow.d.ts +13 -0
- package/dist/src/databases/entities/SharedWorkflow.js +83 -0
- package/dist/src/databases/entities/SharedWorkflow.js.map +1 -0
- package/dist/src/databases/entities/TagEntity.js +6 -2
- package/dist/src/databases/entities/TagEntity.js.map +1 -1
- package/dist/src/databases/entities/User.d.ts +24 -0
- package/dist/src/databases/entities/User.js +145 -0
- package/dist/src/databases/entities/User.js.map +1 -0
- package/dist/src/databases/entities/WorkflowEntity.d.ts +2 -0
- package/dist/src/databases/entities/WorkflowEntity.js +8 -1
- package/dist/src/databases/entities/WorkflowEntity.js.map +1 -1
- package/dist/src/databases/entities/index.d.ts +10 -0
- package/dist/src/databases/entities/index.js +10 -0
- package/dist/src/databases/entities/index.js.map +1 -1
- package/dist/src/databases/mysqldb/migrations/1626183952959-AddWaitColumn.js +0 -1
- package/dist/src/databases/mysqldb/migrations/1626183952959-AddWaitColumn.js.map +1 -1
- package/dist/src/databases/mysqldb/migrations/1630451444017-UpdateWorkflowCredentials.js +0 -3
- package/dist/src/databases/mysqldb/migrations/1630451444017-UpdateWorkflowCredentials.js.map +1 -1
- package/dist/src/databases/mysqldb/migrations/1644424784709-AddExecutionEntityIndexes.js +21 -8
- package/dist/src/databases/mysqldb/migrations/1644424784709-AddExecutionEntityIndexes.js.map +1 -1
- package/dist/src/databases/mysqldb/migrations/1646992772331-CreateUserManagement.d.ts +6 -0
- package/dist/src/databases/mysqldb/migrations/1646992772331-CreateUserManagement.js +100 -0
- package/dist/src/databases/mysqldb/migrations/1646992772331-CreateUserManagement.js.map +1 -0
- package/dist/src/databases/mysqldb/migrations/index.js +2 -0
- package/dist/src/databases/mysqldb/migrations/index.js.map +1 -1
- package/dist/src/databases/postgresdb/migrations/1620824779533-UniqueWorkflowNames.d.ts +1 -1
- package/dist/src/databases/postgresdb/migrations/1620824779533-UniqueWorkflowNames.js +1 -1
- package/dist/src/databases/postgresdb/migrations/1620824779533-UniqueWorkflowNames.js.map +1 -1
- package/dist/src/databases/postgresdb/migrations/1626176912946-AddwaitTill.js +0 -1
- package/dist/src/databases/postgresdb/migrations/1626176912946-AddwaitTill.js.map +1 -1
- package/dist/src/databases/postgresdb/migrations/1630419189837-UpdateWorkflowCredentials.js +0 -3
- package/dist/src/databases/postgresdb/migrations/1630419189837-UpdateWorkflowCredentials.js.map +1 -1
- package/dist/src/databases/postgresdb/migrations/1644422880309-AddExecutionEntityIndexes.js +16 -17
- package/dist/src/databases/postgresdb/migrations/1644422880309-AddExecutionEntityIndexes.js.map +1 -1
- package/dist/src/databases/postgresdb/migrations/1646992772331-CreateUserManagement.d.ts +6 -0
- package/dist/src/databases/postgresdb/migrations/1646992772331-CreateUserManagement.js +106 -0
- package/dist/src/databases/postgresdb/migrations/1646992772331-CreateUserManagement.js.map +1 -0
- package/dist/src/databases/postgresdb/migrations/index.js +2 -0
- package/dist/src/databases/postgresdb/migrations/index.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1588102412422-InitialMigration.js +3 -0
- package/dist/src/databases/sqlite/migrations/1588102412422-InitialMigration.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1592445003908-WebhookModel.js +3 -0
- package/dist/src/databases/sqlite/migrations/1592445003908-WebhookModel.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1594825041918-CreateIndexStoppedAt.d.ts +1 -1
- package/dist/src/databases/sqlite/migrations/1594825041918-CreateIndexStoppedAt.js +3 -0
- package/dist/src/databases/sqlite/migrations/1594825041918-CreateIndexStoppedAt.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1607431743769-MakeStoppedAtNullable.d.ts +2 -1
- package/dist/src/databases/sqlite/migrations/1607431743769-MakeStoppedAtNullable.js +6 -0
- package/dist/src/databases/sqlite/migrations/1607431743769-MakeStoppedAtNullable.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1611071044839-AddWebhookId.d.ts +1 -1
- package/dist/src/databases/sqlite/migrations/1611071044839-AddWebhookId.js +3 -0
- package/dist/src/databases/sqlite/migrations/1611071044839-AddWebhookId.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1617213344594-CreateTagEntity.d.ts +1 -1
- package/dist/src/databases/sqlite/migrations/1617213344594-CreateTagEntity.js +3 -0
- package/dist/src/databases/sqlite/migrations/1617213344594-CreateTagEntity.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1620821879465-UniqueWorkflowNames.d.ts +1 -1
- package/dist/src/databases/sqlite/migrations/1620821879465-UniqueWorkflowNames.js +3 -0
- package/dist/src/databases/sqlite/migrations/1620821879465-UniqueWorkflowNames.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1621707690587-AddWaitColumn.js +3 -1
- package/dist/src/databases/sqlite/migrations/1621707690587-AddWaitColumn.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1630330987096-UpdateWorkflowCredentials.js +3 -3
- package/dist/src/databases/sqlite/migrations/1630330987096-UpdateWorkflowCredentials.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1644421939510-AddExecutionEntityIndexes.js +17 -13
- package/dist/src/databases/sqlite/migrations/1644421939510-AddExecutionEntityIndexes.js.map +1 -1
- package/dist/src/databases/sqlite/migrations/1646992772331-CreateUserManagement.d.ts +6 -0
- package/dist/src/databases/sqlite/migrations/1646992772331-CreateUserManagement.js +73 -0
- package/dist/src/databases/sqlite/migrations/1646992772331-CreateUserManagement.js.map +1 -0
- package/dist/src/databases/sqlite/migrations/index.d.ts +3 -2
- package/dist/src/databases/sqlite/migrations/index.js +4 -1
- package/dist/src/databases/sqlite/migrations/index.js.map +1 -1
- package/dist/src/databases/utils/customValidators.d.ts +1 -0
- package/dist/src/databases/utils/customValidators.js +22 -0
- package/dist/src/databases/utils/customValidators.js.map +1 -0
- package/dist/src/databases/utils/migrationHelpers.d.ts +3 -0
- package/dist/src/databases/utils/migrationHelpers.js +60 -0
- package/dist/src/databases/utils/migrationHelpers.js.map +1 -0
- package/dist/src/databases/utils/transformers.d.ts +9 -0
- package/dist/src/databases/utils/transformers.js +16 -0
- package/dist/src/databases/utils/transformers.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +4 -1
- package/dist/src/telemetry/index.js +4 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/test/{CredentialsHelper.test.d.ts → integration/auth.endpoints.test.d.ts} +0 -0
- package/dist/test/integration/auth.endpoints.test.js +99 -0
- package/dist/test/integration/auth.endpoints.test.js.map +1 -0
- package/dist/test/integration/auth.middleware.test.d.ts +1 -0
- package/dist/test/integration/auth.middleware.test.js +46 -0
- package/dist/test/integration/auth.middleware.test.js.map +1 -0
- package/dist/test/integration/credentials.api.test.d.ts +1 -0
- package/dist/test/integration/credentials.api.test.js +401 -0
- package/dist/test/integration/credentials.api.test.js.map +1 -0
- package/dist/test/integration/me.endpoints.test.d.ts +1 -0
- package/dist/test/integration/me.endpoints.test.js +383 -0
- package/dist/test/integration/me.endpoints.test.js.map +1 -0
- package/dist/test/integration/owner.endpoints.test.d.ts +1 -0
- package/dist/test/integration/owner.endpoints.test.js +125 -0
- package/dist/test/integration/owner.endpoints.test.js.map +1 -0
- package/dist/test/integration/passwordReset.endpoints.test.d.ts +1 -0
- package/dist/test/integration/passwordReset.endpoints.test.js +221 -0
- package/dist/test/integration/passwordReset.endpoints.test.js.map +1 -0
- package/dist/test/integration/shared/constants.d.ts +16 -0
- package/dist/test/integration/shared/constants.js +41 -0
- package/dist/test/integration/shared/constants.js.map +1 -0
- package/dist/test/integration/shared/random.d.ts +5 -0
- package/dist/test/integration/shared/random.js +34 -0
- package/dist/test/integration/shared/random.js.map +1 -0
- package/dist/test/integration/shared/testDb.d.ts +47 -0
- package/dist/test/integration/shared/testDb.js +280 -0
- package/dist/test/integration/shared/testDb.js.map +1 -0
- package/dist/test/integration/shared/utils.d.ts +20 -0
- package/dist/test/integration/shared/utils.js +132 -0
- package/dist/test/integration/shared/utils.js.map +1 -0
- package/dist/test/integration/users.endpoints.test.d.ts +1 -0
- package/dist/test/integration/users.endpoints.test.js +420 -0
- package/dist/test/integration/users.endpoints.test.js.map +1 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +27 -0
- package/dist/test/setup.js.map +1 -0
- package/dist/test/teardown.d.ts +2 -0
- package/dist/test/teardown.js +33 -0
- package/dist/test/teardown.js.map +1 -0
- package/dist/test/unit/CredentialsHelper.test.d.ts +1 -0
- package/dist/test/{CredentialsHelper.test.js → unit/CredentialsHelper.test.js} +1 -1
- package/dist/test/unit/CredentialsHelper.test.js.map +1 -0
- package/dist/test/{Helpers.d.ts → unit/Helpers.d.ts} +0 -0
- package/dist/test/{Helpers.js → unit/Helpers.js} +0 -0
- package/dist/test/unit/Helpers.js.map +1 -0
- package/oclif.manifest.json +1 -1
- package/package.json +30 -29
- package/dist/src/PersonalizationSurvey.d.ts +0 -3
- package/dist/src/PersonalizationSurvey.js +0 -48
- package/dist/src/PersonalizationSurvey.js.map +0 -1
- package/dist/test/CredentialsHelper.test.js.map +0 -1
- package/dist/test/Helpers.js.map +0 -1
package/dist/src/Server.js
CHANGED
|
@@ -11,13 +11,15 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.start = void 0;
|
|
14
|
+
exports.start = exports.externalHooks = void 0;
|
|
15
15
|
const express = require("express");
|
|
16
16
|
const fs_1 = require("fs");
|
|
17
17
|
const promises_1 = require("fs/promises");
|
|
18
|
+
const lodash_1 = require("lodash");
|
|
18
19
|
const path_1 = require("path");
|
|
19
20
|
const typeorm_1 = require("typeorm");
|
|
20
21
|
const bodyParser = require("body-parser");
|
|
22
|
+
const cookieParser = require("cookie-parser");
|
|
21
23
|
const history = require("connect-history-api-fallback");
|
|
22
24
|
const os = require("os");
|
|
23
25
|
const _ = require("lodash");
|
|
@@ -41,13 +43,21 @@ const Queue = require("./Queue");
|
|
|
41
43
|
const _1 = require(".");
|
|
42
44
|
const config = require("../config");
|
|
43
45
|
const TagHelpers = require("./TagHelpers");
|
|
44
|
-
const PersonalizationSurvey = require("./PersonalizationSurvey");
|
|
45
46
|
const InternalHooksManager_1 = require("./InternalHooksManager");
|
|
46
47
|
const TagEntity_1 = require("./databases/entities/TagEntity");
|
|
47
48
|
const WorkflowEntity_1 = require("./databases/entities/WorkflowEntity");
|
|
49
|
+
const WorkflowHelpers_1 = require("./WorkflowHelpers");
|
|
48
50
|
const TranslationHelpers_1 = require("./TranslationHelpers");
|
|
49
51
|
const WebhookHelpers_1 = require("./WebhookHelpers");
|
|
52
|
+
const UserManagement_1 = require("./UserManagement");
|
|
53
|
+
const jwt_1 = require("./UserManagement/auth/jwt");
|
|
54
|
+
const GenericHelpers_1 = require("./GenericHelpers");
|
|
55
|
+
const SharedWorkflow_1 = require("./databases/entities/SharedWorkflow");
|
|
56
|
+
const constants_1 = require("./constants");
|
|
57
|
+
const credentials_api_1 = require("./api/credentials.api");
|
|
58
|
+
const UserManagementHelper_1 = require("./UserManagement/UserManagementHelper");
|
|
50
59
|
require('body-parser-xml')(bodyParser);
|
|
60
|
+
exports.externalHooks = _1.ExternalHooks();
|
|
51
61
|
class App {
|
|
52
62
|
constructor() {
|
|
53
63
|
this.app = express();
|
|
@@ -72,7 +82,7 @@ class App {
|
|
|
72
82
|
this.protocol = config.get('protocol');
|
|
73
83
|
this.sslKey = config.get('ssl_key');
|
|
74
84
|
this.sslCert = config.get('ssl_cert');
|
|
75
|
-
this.externalHooks =
|
|
85
|
+
this.externalHooks = exports.externalHooks;
|
|
76
86
|
this.presetCredentialsLoaded = false;
|
|
77
87
|
this.endpointPresetCredentials = config.get('credentials.overwrite.endpoint');
|
|
78
88
|
const urlBaseWebhook = _1.WebhookHelpers.getWebhookBaseUrl();
|
|
@@ -98,6 +108,7 @@ class App {
|
|
|
98
108
|
maxExecutionTimeout: this.maxExecutionTimeout,
|
|
99
109
|
timezone: this.timezone,
|
|
100
110
|
urlBaseWebhook,
|
|
111
|
+
urlBaseEditor: UserManagementHelper_1.getInstanceBaseUrl(),
|
|
101
112
|
versionCli: '',
|
|
102
113
|
oauthCallbackUrls: {
|
|
103
114
|
oauth1: `${urlBaseWebhook}${this.restEndpoint}/oauth1-credential/callback`,
|
|
@@ -110,10 +121,17 @@ class App {
|
|
|
110
121
|
},
|
|
111
122
|
instanceId: '',
|
|
112
123
|
telemetry: telemetrySettings,
|
|
113
|
-
|
|
114
|
-
shouldShow: false,
|
|
115
|
-
},
|
|
124
|
+
personalizationSurveyEnabled: config.get('personalization.enabled') && config.get('diagnostics.enabled'),
|
|
116
125
|
defaultLocale: config.get('defaultLocale'),
|
|
126
|
+
userManagement: {
|
|
127
|
+
enabled: config.get('userManagement.disabled') === false ||
|
|
128
|
+
config.get('userManagement.isInstanceOwnerSetUp') === true,
|
|
129
|
+
showSetupOnFirstLoad: config.get('userManagement.disabled') === false &&
|
|
130
|
+
config.get('userManagement.isInstanceOwnerSetUp') === false &&
|
|
131
|
+
config.get('userManagement.skipInstanceOwnerSetup') === false,
|
|
132
|
+
smtpSetup: UserManagementHelper_1.isEmailSetUp(),
|
|
133
|
+
},
|
|
134
|
+
workflowTagsDisabled: config.get('workflowTagsDisabled'),
|
|
117
135
|
logLevel: config.get('logs.level'),
|
|
118
136
|
hiringBannerEnabled: config.get('hiringBanner.enabled'),
|
|
119
137
|
templates: {
|
|
@@ -125,6 +143,16 @@ class App {
|
|
|
125
143
|
getCurrentDate() {
|
|
126
144
|
return new Date();
|
|
127
145
|
}
|
|
146
|
+
getSettingsForFrontend() {
|
|
147
|
+
Object.assign(this.frontendSettings.userManagement, {
|
|
148
|
+
enabled: config.get('userManagement.disabled') === false ||
|
|
149
|
+
config.get('userManagement.isInstanceOwnerSetUp') === true,
|
|
150
|
+
showSetupOnFirstLoad: config.get('userManagement.disabled') === false &&
|
|
151
|
+
config.get('userManagement.isInstanceOwnerSetUp') === false &&
|
|
152
|
+
config.get('userManagement.skipInstanceOwnerSetup') === false,
|
|
153
|
+
});
|
|
154
|
+
return this.frontendSettings;
|
|
155
|
+
}
|
|
128
156
|
async config() {
|
|
129
157
|
const enableMetrics = config.get('endpoints.metrics.enable');
|
|
130
158
|
let register;
|
|
@@ -137,8 +165,6 @@ class App {
|
|
|
137
165
|
this.versions = await _1.GenericHelpers.getVersions();
|
|
138
166
|
this.frontendSettings.versionCli = this.versions.cli;
|
|
139
167
|
this.frontendSettings.instanceId = await n8n_core_1.UserSettings.getInstanceId();
|
|
140
|
-
this.frontendSettings.personalizationSurvey =
|
|
141
|
-
await PersonalizationSurvey.preparePersonalizationSurvey();
|
|
142
168
|
await this.externalHooks.run('frontend.settings', [this.frontendSettings]);
|
|
143
169
|
const excludeEndpoints = config.get('security.excludeEndpoints');
|
|
144
170
|
const ignoredEndpoints = [
|
|
@@ -163,7 +189,7 @@ class App {
|
|
|
163
189
|
const basicAuthHashEnabled = (await _1.GenericHelpers.getConfigValue('security.basicAuth.hash'));
|
|
164
190
|
let validPassword = null;
|
|
165
191
|
this.app.use(async (req, res, next) => {
|
|
166
|
-
if (authIgnoreRegex.exec(req.url)) {
|
|
192
|
+
if (authIgnoreRegex.exec(req.url) || config.get('userManagement.isInstanceOwnerSetUp')) {
|
|
167
193
|
return next();
|
|
168
194
|
}
|
|
169
195
|
const realm = 'n8n - Editor UI';
|
|
@@ -254,12 +280,22 @@ class App {
|
|
|
254
280
|
});
|
|
255
281
|
});
|
|
256
282
|
}
|
|
257
|
-
this.app.use((
|
|
283
|
+
this.app.use(cookieParser());
|
|
284
|
+
this.app.use(async (req, res, next) => {
|
|
285
|
+
var _a, _b;
|
|
258
286
|
if (req.url.indexOf(`/${this.restEndpoint}/push`) === 0) {
|
|
259
287
|
if (req.query.sessionId === undefined) {
|
|
260
288
|
next(new Error('The query parameter "sessionId" is missing!'));
|
|
261
289
|
return;
|
|
262
290
|
}
|
|
291
|
+
try {
|
|
292
|
+
const authCookie = (_b = (_a = req.cookies) === null || _a === void 0 ? void 0 : _a[constants_1.AUTH_COOKIE_NAME]) !== null && _b !== void 0 ? _b : '';
|
|
293
|
+
await jwt_1.resolveJwt(authCookie);
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
res.status(401).send('Unauthorized');
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
263
299
|
this.push.add(req.query.sessionId, req, res);
|
|
264
300
|
return;
|
|
265
301
|
}
|
|
@@ -311,6 +347,7 @@ class App {
|
|
|
311
347
|
if (process.env.NODE_ENV !== 'production') {
|
|
312
348
|
this.app.use((req, res, next) => {
|
|
313
349
|
res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
|
|
350
|
+
res.header('Access-Control-Allow-Credentials', 'true');
|
|
314
351
|
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
|
|
315
352
|
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, sessionid');
|
|
316
353
|
next();
|
|
@@ -323,6 +360,8 @@ class App {
|
|
|
323
360
|
}
|
|
324
361
|
next();
|
|
325
362
|
});
|
|
363
|
+
await UserManagement_1.userManagementRouter.addRoutes.apply(this, [ignoredEndpoints, this.restEndpoint]);
|
|
364
|
+
this.app.use(`/${this.restEndpoint}/credentials`, credentials_api_1.credentialsController);
|
|
326
365
|
this.app.get('/healthz', async (req, res) => {
|
|
327
366
|
n8n_workflow_1.LoggerProxy.debug('Health check started!');
|
|
328
367
|
const connection = typeorm_1.getConnectionManager().get();
|
|
@@ -350,29 +389,47 @@ class App {
|
|
|
350
389
|
_1.ResponseHelper.sendSuccessResponse(res, response, true, 200);
|
|
351
390
|
});
|
|
352
391
|
}
|
|
353
|
-
this.app.post(`/${this.restEndpoint}/workflows`, _1.ResponseHelper.send(async (req
|
|
392
|
+
this.app.post(`/${this.restEndpoint}/workflows`, _1.ResponseHelper.send(async (req) => {
|
|
354
393
|
delete req.body.id;
|
|
355
|
-
const incomingData = req.body;
|
|
356
394
|
const newWorkflow = new WorkflowEntity_1.WorkflowEntity();
|
|
357
|
-
Object.assign(newWorkflow,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
395
|
+
Object.assign(newWorkflow, req.body);
|
|
396
|
+
await GenericHelpers_1.validateEntity(newWorkflow);
|
|
397
|
+
await this.externalHooks.run('workflow.create', [newWorkflow]);
|
|
398
|
+
const { tags: tagIds } = req.body;
|
|
399
|
+
if ((tagIds === null || tagIds === void 0 ? void 0 : tagIds.length) && !config.get('workflowTagsDisabled')) {
|
|
400
|
+
newWorkflow.tags = await _1.Db.collections.Tag.findByIds(tagIds, {
|
|
362
401
|
select: ['id', 'name'],
|
|
363
402
|
});
|
|
364
403
|
}
|
|
365
404
|
await _1.WorkflowHelpers.replaceInvalidCredentials(newWorkflow);
|
|
366
|
-
|
|
367
|
-
await
|
|
368
|
-
|
|
369
|
-
.
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
405
|
+
let savedWorkflow;
|
|
406
|
+
await typeorm_1.getConnection().transaction(async (transactionManager) => {
|
|
407
|
+
savedWorkflow = await transactionManager.save(newWorkflow);
|
|
408
|
+
const role = await _1.Db.collections.Role.findOneOrFail({
|
|
409
|
+
name: 'owner',
|
|
410
|
+
scope: 'workflow',
|
|
411
|
+
});
|
|
412
|
+
const newSharedWorkflow = new SharedWorkflow_1.SharedWorkflow();
|
|
413
|
+
Object.assign(newSharedWorkflow, {
|
|
414
|
+
role,
|
|
415
|
+
user: req.user,
|
|
416
|
+
workflow: savedWorkflow,
|
|
417
|
+
});
|
|
418
|
+
await transactionManager.save(newSharedWorkflow);
|
|
419
|
+
});
|
|
420
|
+
if (!savedWorkflow) {
|
|
421
|
+
n8n_workflow_1.LoggerProxy.error('Failed to create workflow', { userId: req.user.id });
|
|
422
|
+
throw new _1.ResponseHelper.ResponseError('Failed to save workflow');
|
|
423
|
+
}
|
|
424
|
+
if (tagIds && !config.get('workflowTagsDisabled')) {
|
|
425
|
+
savedWorkflow.tags = TagHelpers.sortByRequestOrder(savedWorkflow.tags, {
|
|
426
|
+
requestOrder: tagIds,
|
|
427
|
+
});
|
|
428
|
+
}
|
|
373
429
|
await this.externalHooks.run('workflow.afterCreate', [savedWorkflow]);
|
|
374
|
-
void InternalHooksManager_1.InternalHooksManager.getInstance().onWorkflowCreated(newWorkflow);
|
|
375
|
-
|
|
430
|
+
void InternalHooksManager_1.InternalHooksManager.getInstance().onWorkflowCreated(req.user.id, newWorkflow);
|
|
431
|
+
const { id } = savedWorkflow, rest = __rest(savedWorkflow, ["id"]);
|
|
432
|
+
return Object.assign({ id: id.toString() }, rest);
|
|
376
433
|
}));
|
|
377
434
|
this.app.get(`/${this.restEndpoint}/workflows/from-url`, _1.ResponseHelper.send(async (req, res) => {
|
|
378
435
|
if (req.query.url === undefined) {
|
|
@@ -399,45 +456,92 @@ class App {
|
|
|
399
456
|
}
|
|
400
457
|
return workflowData;
|
|
401
458
|
}));
|
|
402
|
-
this.app.get(`/${this.restEndpoint}/workflows`, _1.ResponseHelper.send(async (req
|
|
403
|
-
|
|
459
|
+
this.app.get(`/${this.restEndpoint}/workflows`, _1.ResponseHelper.send(async (req) => {
|
|
460
|
+
let workflows = [];
|
|
461
|
+
const filter = req.query.filter ? JSON.parse(req.query.filter) : {};
|
|
462
|
+
const query = {
|
|
404
463
|
select: ['id', 'name', 'active', 'createdAt', 'updatedAt'],
|
|
405
464
|
relations: ['tags'],
|
|
406
465
|
};
|
|
407
|
-
if (
|
|
408
|
-
|
|
466
|
+
if (config.get('workflowTagsDisabled')) {
|
|
467
|
+
delete query.relations;
|
|
409
468
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
469
|
+
if (req.user.globalRole.name === 'owner') {
|
|
470
|
+
workflows = await _1.Db.collections.Workflow.find(Object.assign(query, {
|
|
471
|
+
where: filter,
|
|
472
|
+
}));
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
const shared = await _1.Db.collections.SharedWorkflow.find({
|
|
476
|
+
relations: ['workflow'],
|
|
477
|
+
where: WorkflowHelpers_1.whereClause({
|
|
478
|
+
user: req.user,
|
|
479
|
+
entityType: 'workflow',
|
|
480
|
+
}),
|
|
481
|
+
});
|
|
482
|
+
if (!shared.length)
|
|
483
|
+
return [];
|
|
484
|
+
workflows = await _1.Db.collections.Workflow.find(Object.assign(query, {
|
|
485
|
+
where: Object.assign({ id: typeorm_1.In(shared.map(({ workflow }) => workflow.id)) }, filter),
|
|
486
|
+
}));
|
|
487
|
+
}
|
|
488
|
+
return workflows.map((workflow) => {
|
|
489
|
+
const { id } = workflow, rest = __rest(workflow, ["id"]);
|
|
490
|
+
return Object.assign({ id: id.toString() }, rest);
|
|
414
491
|
});
|
|
415
|
-
return workflows;
|
|
416
492
|
}));
|
|
417
|
-
this.app.get(`/${this.restEndpoint}/workflows/new`, _1.ResponseHelper.send(async (req
|
|
493
|
+
this.app.get(`/${this.restEndpoint}/workflows/new`, _1.ResponseHelper.send(async (req) => {
|
|
418
494
|
const requestedName = req.query.name && req.query.name !== '' ? req.query.name : this.defaultWorkflowName;
|
|
419
495
|
return await _1.GenericHelpers.generateUniqueName(requestedName, 'workflow');
|
|
420
496
|
}));
|
|
421
|
-
this.app.get(`/${this.restEndpoint}/workflows/:id`, _1.ResponseHelper.send(async (req
|
|
422
|
-
const
|
|
423
|
-
|
|
497
|
+
this.app.get(`/${this.restEndpoint}/workflows/:id`, _1.ResponseHelper.send(async (req) => {
|
|
498
|
+
const { id: workflowId } = req.params;
|
|
499
|
+
let relations = ['workflow', 'workflow.tags'];
|
|
500
|
+
if (config.get('workflowTagsDisabled')) {
|
|
501
|
+
relations = relations.filter((relation) => relation !== 'workflow.tags');
|
|
502
|
+
}
|
|
503
|
+
const shared = await _1.Db.collections.SharedWorkflow.findOne({
|
|
504
|
+
relations,
|
|
505
|
+
where: WorkflowHelpers_1.whereClause({
|
|
506
|
+
user: req.user,
|
|
507
|
+
entityType: 'workflow',
|
|
508
|
+
entityId: workflowId,
|
|
509
|
+
}),
|
|
424
510
|
});
|
|
425
|
-
if (
|
|
426
|
-
|
|
511
|
+
if (!shared) {
|
|
512
|
+
n8n_workflow_1.LoggerProxy.info('User attempted to access a workflow without permissions', {
|
|
513
|
+
workflowId,
|
|
514
|
+
userId: req.user.id,
|
|
515
|
+
});
|
|
516
|
+
throw new _1.ResponseHelper.ResponseError(`Workflow with ID "${workflowId}" could not be found.`, undefined, 404);
|
|
427
517
|
}
|
|
428
|
-
workflow
|
|
429
|
-
|
|
430
|
-
return workflow;
|
|
518
|
+
const _a = shared.workflow, { id } = _a, rest = __rest(_a, ["id"]);
|
|
519
|
+
return Object.assign({ id: id.toString() }, rest);
|
|
431
520
|
}));
|
|
432
|
-
this.app.patch(`/${this.restEndpoint}/workflows/:id`, _1.ResponseHelper.send(async (req
|
|
433
|
-
const
|
|
434
|
-
const
|
|
435
|
-
|
|
521
|
+
this.app.patch(`/${this.restEndpoint}/workflows/:id`, _1.ResponseHelper.send(async (req) => {
|
|
522
|
+
const { id: workflowId } = req.params;
|
|
523
|
+
const updateData = new WorkflowEntity_1.WorkflowEntity();
|
|
524
|
+
const _a = req.body, { tags } = _a, rest = __rest(_a, ["tags"]);
|
|
525
|
+
Object.assign(updateData, rest);
|
|
526
|
+
const shared = await _1.Db.collections.SharedWorkflow.findOne({
|
|
527
|
+
relations: ['workflow'],
|
|
528
|
+
where: WorkflowHelpers_1.whereClause({
|
|
529
|
+
user: req.user,
|
|
530
|
+
entityType: 'workflow',
|
|
531
|
+
entityId: workflowId,
|
|
532
|
+
}),
|
|
533
|
+
});
|
|
534
|
+
if (!shared) {
|
|
535
|
+
n8n_workflow_1.LoggerProxy.info('User attempted to update a workflow without permissions', {
|
|
536
|
+
workflowId,
|
|
537
|
+
userId: req.user.id,
|
|
538
|
+
});
|
|
539
|
+
throw new _1.ResponseHelper.ResponseError(`Workflow with ID "${workflowId}" could not be found to be updated.`, undefined, 404);
|
|
540
|
+
}
|
|
436
541
|
await _1.WorkflowHelpers.replaceInvalidCredentials(updateData);
|
|
437
542
|
await this.externalHooks.run('workflow.update', [updateData]);
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
await this.activeWorkflowRunner.remove(id);
|
|
543
|
+
if (shared.workflow.active) {
|
|
544
|
+
await this.activeWorkflowRunner.remove(workflowId);
|
|
441
545
|
}
|
|
442
546
|
if (updateData.settings) {
|
|
443
547
|
if (updateData.settings.timezone === 'DEFAULT') {
|
|
@@ -456,55 +560,78 @@ class App {
|
|
|
456
560
|
delete updateData.settings.executionTimeout;
|
|
457
561
|
}
|
|
458
562
|
}
|
|
459
|
-
updateData.
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
if (tags) {
|
|
563
|
+
if (updateData.name) {
|
|
564
|
+
updateData.updatedAt = this.getCurrentDate();
|
|
565
|
+
await GenericHelpers_1.validateEntity(updateData);
|
|
566
|
+
}
|
|
567
|
+
await _1.Db.collections.Workflow.update(workflowId, updateData);
|
|
568
|
+
if (tags && !config.get('workflowTagsDisabled')) {
|
|
465
569
|
const tablePrefix = config.get('database.tablePrefix');
|
|
466
|
-
await TagHelpers.removeRelations(
|
|
570
|
+
await TagHelpers.removeRelations(workflowId, tablePrefix);
|
|
467
571
|
if (tags.length) {
|
|
468
|
-
await TagHelpers.createRelations(
|
|
572
|
+
await TagHelpers.createRelations(workflowId, tags, tablePrefix);
|
|
469
573
|
}
|
|
470
574
|
}
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
575
|
+
const options = {
|
|
576
|
+
relations: ['tags'],
|
|
577
|
+
};
|
|
578
|
+
if (config.get('workflowTagsDisabled')) {
|
|
579
|
+
delete options.relations;
|
|
580
|
+
}
|
|
581
|
+
const updatedWorkflow = await _1.Db.collections.Workflow.findOne(workflowId, options);
|
|
582
|
+
if (updatedWorkflow === undefined) {
|
|
583
|
+
throw new _1.ResponseHelper.ResponseError(`Workflow with ID "${workflowId}" could not be found to be updated.`, undefined, 400);
|
|
474
584
|
}
|
|
475
|
-
if (tags === null || tags === void 0 ? void 0 : tags.length) {
|
|
476
|
-
|
|
585
|
+
if (updatedWorkflow.tags.length && (tags === null || tags === void 0 ? void 0 : tags.length)) {
|
|
586
|
+
updatedWorkflow.tags = TagHelpers.sortByRequestOrder(updatedWorkflow.tags, {
|
|
587
|
+
requestOrder: tags,
|
|
588
|
+
});
|
|
477
589
|
}
|
|
478
|
-
await this.externalHooks.run('workflow.afterUpdate', [
|
|
479
|
-
void InternalHooksManager_1.InternalHooksManager.getInstance().onWorkflowSaved(
|
|
480
|
-
if (
|
|
590
|
+
await this.externalHooks.run('workflow.afterUpdate', [updatedWorkflow]);
|
|
591
|
+
void InternalHooksManager_1.InternalHooksManager.getInstance().onWorkflowSaved(req.user.id, updatedWorkflow);
|
|
592
|
+
if (updatedWorkflow.active) {
|
|
481
593
|
try {
|
|
482
|
-
await this.externalHooks.run('workflow.activate', [
|
|
483
|
-
await this.activeWorkflowRunner.add(
|
|
594
|
+
await this.externalHooks.run('workflow.activate', [updatedWorkflow]);
|
|
595
|
+
await this.activeWorkflowRunner.add(workflowId, shared.workflow.active ? 'update' : 'activate');
|
|
484
596
|
}
|
|
485
597
|
catch (error) {
|
|
486
598
|
updateData.active = false;
|
|
487
|
-
await _1.Db.collections.Workflow.update(
|
|
488
|
-
|
|
599
|
+
await _1.Db.collections.Workflow.update(workflowId, updateData);
|
|
600
|
+
updatedWorkflow.active = false;
|
|
489
601
|
throw error;
|
|
490
602
|
}
|
|
491
603
|
}
|
|
492
|
-
|
|
493
|
-
return
|
|
604
|
+
const { id } = updatedWorkflow, remainder = __rest(updatedWorkflow, ["id"]);
|
|
605
|
+
return Object.assign({ id: id.toString() }, remainder);
|
|
494
606
|
}));
|
|
495
|
-
this.app.delete(`/${this.restEndpoint}/workflows/:id`, _1.ResponseHelper.send(async (req
|
|
496
|
-
const { id } = req.params;
|
|
497
|
-
await this.externalHooks.run('workflow.delete', [
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
607
|
+
this.app.delete(`/${this.restEndpoint}/workflows/:id`, _1.ResponseHelper.send(async (req) => {
|
|
608
|
+
const { id: workflowId } = req.params;
|
|
609
|
+
await this.externalHooks.run('workflow.delete', [workflowId]);
|
|
610
|
+
const shared = await _1.Db.collections.SharedWorkflow.findOne({
|
|
611
|
+
relations: ['workflow'],
|
|
612
|
+
where: WorkflowHelpers_1.whereClause({
|
|
613
|
+
user: req.user,
|
|
614
|
+
entityType: 'workflow',
|
|
615
|
+
entityId: workflowId,
|
|
616
|
+
}),
|
|
617
|
+
});
|
|
618
|
+
if (!shared) {
|
|
619
|
+
n8n_workflow_1.LoggerProxy.info('User attempted to delete a workflow without permissions', {
|
|
620
|
+
workflowId,
|
|
621
|
+
userId: req.user.id,
|
|
622
|
+
});
|
|
623
|
+
throw new _1.ResponseHelper.ResponseError(`Workflow with ID "${workflowId}" could not be found to be deleted.`, undefined, 400);
|
|
624
|
+
}
|
|
625
|
+
if (shared.workflow.active) {
|
|
626
|
+
await this.activeWorkflowRunner.remove(workflowId);
|
|
627
|
+
}
|
|
628
|
+
await _1.Db.collections.Workflow.delete(workflowId);
|
|
629
|
+
void InternalHooksManager_1.InternalHooksManager.getInstance().onWorkflowDeleted(req.user.id, workflowId);
|
|
630
|
+
await this.externalHooks.run('workflow.afterDelete', [workflowId]);
|
|
505
631
|
return true;
|
|
506
632
|
}));
|
|
507
633
|
this.app.post(`/${this.restEndpoint}/workflows/run`, _1.ResponseHelper.send(async (req, res) => {
|
|
634
|
+
var _a;
|
|
508
635
|
const { workflowData } = req.body;
|
|
509
636
|
const { runData } = req.body;
|
|
510
637
|
const { startNodes } = req.body;
|
|
@@ -516,10 +643,10 @@ class App {
|
|
|
516
643
|
startNodes === undefined ||
|
|
517
644
|
startNodes.length === 0 ||
|
|
518
645
|
destinationNode === undefined) {
|
|
519
|
-
const additionalData = await _1.WorkflowExecuteAdditionalData.getBase();
|
|
646
|
+
const additionalData = await _1.WorkflowExecuteAdditionalData.getBase(req.user.id);
|
|
520
647
|
const nodeTypes = _1.NodeTypes();
|
|
521
648
|
const workflowInstance = new n8n_workflow_1.Workflow({
|
|
522
|
-
id: workflowData.id,
|
|
649
|
+
id: (_a = workflowData.id) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
523
650
|
name: workflowData.name,
|
|
524
651
|
nodes: workflowData.nodes,
|
|
525
652
|
connections: workflowData.connections,
|
|
@@ -543,6 +670,7 @@ class App {
|
|
|
543
670
|
sessionId,
|
|
544
671
|
startNodes,
|
|
545
672
|
workflowData,
|
|
673
|
+
userId: req.user.id,
|
|
546
674
|
};
|
|
547
675
|
const workflowRunner = new _1.WorkflowRunner();
|
|
548
676
|
const executionId = await workflowRunner.run(data);
|
|
@@ -551,61 +679,68 @@ class App {
|
|
|
551
679
|
};
|
|
552
680
|
}));
|
|
553
681
|
this.app.get(`/${this.restEndpoint}/tags`, _1.ResponseHelper.send(async (req, res) => {
|
|
682
|
+
if (config.get('workflowTagsDisabled')) {
|
|
683
|
+
throw new _1.ResponseHelper.ResponseError('Workflow tags are disabled');
|
|
684
|
+
}
|
|
554
685
|
if (req.query.withUsageCount === 'true') {
|
|
555
686
|
const tablePrefix = config.get('database.tablePrefix');
|
|
556
687
|
return TagHelpers.getTagsWithCountDb(tablePrefix);
|
|
557
688
|
}
|
|
558
|
-
|
|
559
|
-
tags.forEach((tag) => (tag.id = tag.id.toString()));
|
|
560
|
-
return tags;
|
|
689
|
+
return _1.Db.collections.Tag.find({ select: ['id', 'name'] });
|
|
561
690
|
}));
|
|
562
691
|
this.app.post(`/${this.restEndpoint}/tags`, _1.ResponseHelper.send(async (req, res) => {
|
|
692
|
+
if (config.get('workflowTagsDisabled')) {
|
|
693
|
+
throw new _1.ResponseHelper.ResponseError('Workflow tags are disabled');
|
|
694
|
+
}
|
|
563
695
|
const newTag = new TagEntity_1.TagEntity();
|
|
564
696
|
newTag.name = req.body.name.trim();
|
|
565
697
|
await this.externalHooks.run('tag.beforeCreate', [newTag]);
|
|
566
|
-
await
|
|
567
|
-
const tag = await _1.Db.collections
|
|
568
|
-
.Tag.save(newTag)
|
|
569
|
-
.catch(TagHelpers.throwDuplicateEntryError);
|
|
698
|
+
await GenericHelpers_1.validateEntity(newTag);
|
|
699
|
+
const tag = await _1.Db.collections.Tag.save(newTag);
|
|
570
700
|
await this.externalHooks.run('tag.afterCreate', [tag]);
|
|
571
|
-
tag.id = tag.id.toString();
|
|
572
701
|
return tag;
|
|
573
702
|
}));
|
|
574
703
|
this.app.patch(`/${this.restEndpoint}/tags/:id`, _1.ResponseHelper.send(async (req, res) => {
|
|
704
|
+
if (config.get('workflowTagsDisabled')) {
|
|
705
|
+
throw new _1.ResponseHelper.ResponseError('Workflow tags are disabled');
|
|
706
|
+
}
|
|
575
707
|
const { name } = req.body;
|
|
576
708
|
const { id } = req.params;
|
|
577
709
|
const newTag = new TagEntity_1.TagEntity();
|
|
578
|
-
newTag.id =
|
|
710
|
+
newTag.id = id;
|
|
579
711
|
newTag.name = name.trim();
|
|
580
712
|
await this.externalHooks.run('tag.beforeUpdate', [newTag]);
|
|
581
|
-
await
|
|
582
|
-
const tag = await _1.Db.collections
|
|
583
|
-
.Tag.save(newTag)
|
|
584
|
-
.catch(TagHelpers.throwDuplicateEntryError);
|
|
713
|
+
await GenericHelpers_1.validateEntity(newTag);
|
|
714
|
+
const tag = await _1.Db.collections.Tag.save(newTag);
|
|
585
715
|
await this.externalHooks.run('tag.afterUpdate', [tag]);
|
|
586
|
-
tag.id = tag.id.toString();
|
|
587
716
|
return tag;
|
|
588
717
|
}));
|
|
589
718
|
this.app.delete(`/${this.restEndpoint}/tags/:id`, _1.ResponseHelper.send(async (req, res) => {
|
|
719
|
+
if (config.get('workflowTagsDisabled')) {
|
|
720
|
+
throw new _1.ResponseHelper.ResponseError('Workflow tags are disabled');
|
|
721
|
+
}
|
|
722
|
+
if (config.get('userManagement.isInstanceOwnerSetUp') === true &&
|
|
723
|
+
req.user.globalRole.name !== 'owner') {
|
|
724
|
+
throw new _1.ResponseHelper.ResponseError('You are not allowed to perform this action', undefined, 403, 'Only owners can remove tags');
|
|
725
|
+
}
|
|
590
726
|
const id = Number(req.params.id);
|
|
591
727
|
await this.externalHooks.run('tag.beforeDelete', [id]);
|
|
592
728
|
await _1.Db.collections.Tag.delete({ id });
|
|
593
729
|
await this.externalHooks.run('tag.afterDelete', [id]);
|
|
594
730
|
return true;
|
|
595
731
|
}));
|
|
596
|
-
this.app.get(`/${this.restEndpoint}/node-parameter-options`, _1.ResponseHelper.send(async (req
|
|
597
|
-
const nodeTypeAndVersion = JSON.parse(
|
|
598
|
-
const path = req.query
|
|
732
|
+
this.app.get(`/${this.restEndpoint}/node-parameter-options`, _1.ResponseHelper.send(async (req) => {
|
|
733
|
+
const nodeTypeAndVersion = JSON.parse(req.query.nodeTypeAndVersion);
|
|
734
|
+
const { path, methodName } = req.query;
|
|
735
|
+
const currentNodeParameters = JSON.parse(req.query.currentNodeParameters);
|
|
599
736
|
let credentials;
|
|
600
|
-
|
|
601
|
-
if (req.query.credentials !== undefined) {
|
|
737
|
+
if (req.query.credentials) {
|
|
602
738
|
credentials = JSON.parse(req.query.credentials);
|
|
603
739
|
}
|
|
604
|
-
const
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
return loadDataInstance.getOptionsViaMethodName(req.query.methodName, additionalData);
|
|
740
|
+
const loadDataInstance = new n8n_core_1.LoadNodeParameterOptions(nodeTypeAndVersion, _1.NodeTypes(), path, currentNodeParameters, credentials);
|
|
741
|
+
const additionalData = await _1.WorkflowExecuteAdditionalData.getBase(req.user.id, currentNodeParameters);
|
|
742
|
+
if (methodName) {
|
|
743
|
+
return loadDataInstance.getOptionsViaMethodName(methodName, additionalData);
|
|
609
744
|
}
|
|
610
745
|
if (req.query.loadOptions) {
|
|
611
746
|
return loadDataInstance.getOptionsViaRequestProperty(JSON.parse(req.query.loadOptions), additionalData);
|
|
@@ -723,144 +858,28 @@ class App {
|
|
|
723
858
|
return _1.ResponseHelper.sendErrorResponse(res, error);
|
|
724
859
|
}
|
|
725
860
|
});
|
|
726
|
-
this.app.get(`/${this.restEndpoint}/active`, _1.ResponseHelper.send(async (req
|
|
727
|
-
const activeWorkflows = await this.activeWorkflowRunner.getActiveWorkflows();
|
|
728
|
-
return activeWorkflows.map((
|
|
729
|
-
}));
|
|
730
|
-
this.app.get(`/${this.restEndpoint}/active/error/:id`, _1.ResponseHelper.send(async (req, res) => {
|
|
731
|
-
const { id } = req.params;
|
|
732
|
-
return this.activeWorkflowRunner.getActivationError(id);
|
|
733
|
-
}));
|
|
734
|
-
this.app.get(`/${this.restEndpoint}/credentials/new`, _1.ResponseHelper.send(async (req, res) => {
|
|
735
|
-
const requestedName = req.query.name && req.query.name !== '' ? req.query.name : this.defaultCredentialsName;
|
|
736
|
-
return await _1.GenericHelpers.generateUniqueName(requestedName, 'credentials');
|
|
737
|
-
}));
|
|
738
|
-
this.app.delete(`/${this.restEndpoint}/credentials/:id`, _1.ResponseHelper.send(async (req, res) => {
|
|
739
|
-
const { id } = req.params;
|
|
740
|
-
await this.externalHooks.run('credentials.delete', [id]);
|
|
741
|
-
await _1.Db.collections.Credentials.delete({ id });
|
|
742
|
-
return true;
|
|
743
|
-
}));
|
|
744
|
-
this.app.post(`/${this.restEndpoint}/credentials`, _1.ResponseHelper.send(async (req, res) => {
|
|
745
|
-
const incomingData = req.body;
|
|
746
|
-
if (!incomingData.name || incomingData.name.length < 3) {
|
|
747
|
-
throw new _1.ResponseHelper.ResponseError(`Credentials name must be at least 3 characters long.`, undefined, 400);
|
|
748
|
-
}
|
|
749
|
-
for (const nodeAccess of incomingData.nodesAccess) {
|
|
750
|
-
nodeAccess.date = this.getCurrentDate();
|
|
751
|
-
}
|
|
752
|
-
const encryptionKey = await n8n_core_1.UserSettings.getEncryptionKey();
|
|
753
|
-
if (encryptionKey === undefined) {
|
|
754
|
-
throw new Error('No encryption key got found to encrypt the credentials!');
|
|
755
|
-
}
|
|
756
|
-
if (incomingData.name === '') {
|
|
757
|
-
throw new Error('Credentials have to have a name set!');
|
|
758
|
-
}
|
|
759
|
-
const credentials = new n8n_core_1.Credentials({ id: null, name: incomingData.name }, incomingData.type, incomingData.nodesAccess);
|
|
760
|
-
credentials.setData(incomingData.data, encryptionKey);
|
|
761
|
-
const newCredentialsData = credentials.getDataToSave();
|
|
762
|
-
await this.externalHooks.run('credentials.create', [newCredentialsData]);
|
|
763
|
-
const result = await _1.Db.collections.Credentials.save(newCredentialsData);
|
|
764
|
-
result.data = incomingData.data;
|
|
765
|
-
result.id = result.id.toString();
|
|
766
|
-
return result;
|
|
767
|
-
}));
|
|
768
|
-
this.app.post(`/${this.restEndpoint}/credentials-test`, _1.ResponseHelper.send(async (req, res) => {
|
|
769
|
-
const incomingData = req.body;
|
|
770
|
-
const encryptionKey = await n8n_core_1.UserSettings.getEncryptionKey();
|
|
771
|
-
if (encryptionKey === undefined) {
|
|
772
|
-
return {
|
|
773
|
-
status: 'Error',
|
|
774
|
-
message: 'No encryption key got found to decrypt the credentials!',
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
const credentialsHelper = new _1.CredentialsHelper(encryptionKey);
|
|
778
|
-
const credentialType = incomingData.credentials.type;
|
|
779
|
-
return credentialsHelper.testCredentials(credentialType, incomingData.credentials, incomingData.nodeToTestWith);
|
|
780
|
-
}));
|
|
781
|
-
this.app.patch(`/${this.restEndpoint}/credentials/:id`, _1.ResponseHelper.send(async (req, res) => {
|
|
782
|
-
const incomingData = req.body;
|
|
783
|
-
const { id } = req.params;
|
|
784
|
-
if (incomingData.name === '') {
|
|
785
|
-
throw new Error('Credentials have to have a name set!');
|
|
786
|
-
}
|
|
787
|
-
for (const nodeAccess of incomingData.nodesAccess) {
|
|
788
|
-
if (!nodeAccess.date) {
|
|
789
|
-
nodeAccess.date = this.getCurrentDate();
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
const encryptionKey = await n8n_core_1.UserSettings.getEncryptionKey();
|
|
793
|
-
if (encryptionKey === undefined) {
|
|
794
|
-
throw new Error('No encryption key got found to encrypt the credentials!');
|
|
795
|
-
}
|
|
796
|
-
const result = await _1.Db.collections.Credentials.findOne(id);
|
|
797
|
-
if (result === undefined) {
|
|
798
|
-
throw new _1.ResponseHelper.ResponseError(`Credentials with the id "${id}" do not exist.`, undefined, 400);
|
|
799
|
-
}
|
|
800
|
-
const currentlySavedCredentials = new n8n_core_1.Credentials(result, result.type, result.nodesAccess, result.data);
|
|
801
|
-
const decryptedData = currentlySavedCredentials.getData(encryptionKey);
|
|
802
|
-
if (decryptedData.oauthTokenData) {
|
|
803
|
-
incomingData.data.oauthTokenData = decryptedData.oauthTokenData;
|
|
804
|
-
}
|
|
805
|
-
const credentials = new n8n_core_1.Credentials({ id, name: incomingData.name }, incomingData.type, incomingData.nodesAccess);
|
|
806
|
-
credentials.setData(incomingData.data, encryptionKey);
|
|
807
|
-
const newCredentialsData = credentials.getDataToSave();
|
|
808
|
-
newCredentialsData.updatedAt = this.getCurrentDate();
|
|
809
|
-
await this.externalHooks.run('credentials.update', [newCredentialsData]);
|
|
810
|
-
await _1.Db.collections.Credentials.update(id, newCredentialsData);
|
|
811
|
-
const responseData = await _1.Db.collections.Credentials.findOne(id);
|
|
812
|
-
if (responseData === undefined) {
|
|
813
|
-
throw new _1.ResponseHelper.ResponseError(`Credentials with id "${id}" could not be found to be updated.`, undefined, 400);
|
|
814
|
-
}
|
|
815
|
-
responseData.data = '';
|
|
816
|
-
responseData.id = responseData.id.toString();
|
|
817
|
-
return responseData;
|
|
818
|
-
}));
|
|
819
|
-
this.app.get(`/${this.restEndpoint}/credentials/:id`, _1.ResponseHelper.send(async (req, res) => {
|
|
820
|
-
const findQuery = {};
|
|
821
|
-
const includeData = ['true', true].includes(req.query.includeData);
|
|
822
|
-
if (!includeData) {
|
|
823
|
-
findQuery.select = ['id', 'name', 'type', 'nodesAccess', 'createdAt', 'updatedAt'];
|
|
824
|
-
}
|
|
825
|
-
const result = await _1.Db.collections.Credentials.findOne(req.params.id);
|
|
826
|
-
if (result === undefined) {
|
|
827
|
-
return result;
|
|
828
|
-
}
|
|
829
|
-
let encryptionKey;
|
|
830
|
-
if (includeData) {
|
|
831
|
-
encryptionKey = await n8n_core_1.UserSettings.getEncryptionKey();
|
|
832
|
-
if (encryptionKey === undefined) {
|
|
833
|
-
throw new Error('No encryption key got found to decrypt the credentials!');
|
|
834
|
-
}
|
|
835
|
-
const credentials = new n8n_core_1.Credentials(result, result.type, result.nodesAccess, result.data);
|
|
836
|
-
result.data = credentials.getData(encryptionKey);
|
|
837
|
-
}
|
|
838
|
-
result.id = result.id.toString();
|
|
839
|
-
return result;
|
|
861
|
+
this.app.get(`/${this.restEndpoint}/active`, _1.ResponseHelper.send(async (req) => {
|
|
862
|
+
const activeWorkflows = await this.activeWorkflowRunner.getActiveWorkflows(req.user);
|
|
863
|
+
return activeWorkflows.map(({ id }) => id.toString());
|
|
840
864
|
}));
|
|
841
|
-
this.app.get(`/${this.restEndpoint}/
|
|
842
|
-
const
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
let result;
|
|
860
|
-
for (result of results) {
|
|
861
|
-
result.id = result.id.toString();
|
|
865
|
+
this.app.get(`/${this.restEndpoint}/active/error/:id`, _1.ResponseHelper.send(async (req) => {
|
|
866
|
+
const { id: workflowId } = req.params;
|
|
867
|
+
const shared = await _1.Db.collections.SharedWorkflow.findOne({
|
|
868
|
+
relations: ['workflow'],
|
|
869
|
+
where: WorkflowHelpers_1.whereClause({
|
|
870
|
+
user: req.user,
|
|
871
|
+
entityType: 'workflow',
|
|
872
|
+
entityId: workflowId,
|
|
873
|
+
}),
|
|
874
|
+
});
|
|
875
|
+
if (!shared) {
|
|
876
|
+
n8n_workflow_1.LoggerProxy.info('User attempted to access workflow errors without permissions', {
|
|
877
|
+
workflowId,
|
|
878
|
+
userId: req.user.id,
|
|
879
|
+
});
|
|
880
|
+
throw new _1.ResponseHelper.ResponseError(`Workflow with ID "${workflowId}" could not be found.`, undefined, 400);
|
|
862
881
|
}
|
|
863
|
-
return
|
|
882
|
+
return this.activeWorkflowRunner.getActivationError(workflowId);
|
|
864
883
|
}));
|
|
865
884
|
this.app.get(`/${this.restEndpoint}/credential-types`, _1.ResponseHelper.send(async (req, res) => {
|
|
866
885
|
const returnData = [];
|
|
@@ -895,26 +914,25 @@ class App {
|
|
|
895
914
|
return _1.ResponseHelper.sendErrorResponse(res, error);
|
|
896
915
|
}
|
|
897
916
|
});
|
|
898
|
-
this.app.get(`/${this.restEndpoint}/oauth1-credential/auth`, _1.ResponseHelper.send(async (req
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
917
|
+
this.app.get(`/${this.restEndpoint}/oauth1-credential/auth`, _1.ResponseHelper.send(async (req) => {
|
|
918
|
+
const { id: credentialId } = req.query;
|
|
919
|
+
if (!credentialId) {
|
|
920
|
+
n8n_workflow_1.LoggerProxy.error('OAuth1 credential authorization failed due to missing credential ID');
|
|
921
|
+
throw new _1.ResponseHelper.ResponseError('Required credential ID is missing', undefined, 400);
|
|
902
922
|
}
|
|
903
|
-
const
|
|
904
|
-
if (
|
|
905
|
-
|
|
906
|
-
|
|
923
|
+
const credential = await _1.getCredentialForUser(credentialId, req.user);
|
|
924
|
+
if (!credential) {
|
|
925
|
+
n8n_workflow_1.LoggerProxy.error('OAuth1 credential authorization failed because the current user does not have the correct permissions', { userId: req.user.id });
|
|
926
|
+
throw new _1.ResponseHelper.ResponseError(constants_1.RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL, undefined, 404);
|
|
907
927
|
}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
res.status(500).send('No encryption key got found to decrypt the credentials!');
|
|
912
|
-
return '';
|
|
928
|
+
const encryptionKey = await n8n_core_1.UserSettings.getEncryptionKey();
|
|
929
|
+
if (!encryptionKey) {
|
|
930
|
+
throw new _1.ResponseHelper.ResponseError(constants_1.RESPONSE_ERROR_MESSAGES.NO_ENCRYPTION_KEY, undefined, 500);
|
|
913
931
|
}
|
|
914
932
|
const mode = 'internal';
|
|
915
933
|
const credentialsHelper = new _1.CredentialsHelper(encryptionKey);
|
|
916
|
-
const decryptedDataOriginal = await credentialsHelper.getDecrypted(
|
|
917
|
-
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal,
|
|
934
|
+
const decryptedDataOriginal = await credentialsHelper.getDecrypted(credential, credential.type, mode, true);
|
|
935
|
+
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal, credential.type, mode);
|
|
918
936
|
const signatureMethod = _.get(oauthCredentials, 'signatureMethod');
|
|
919
937
|
const oAuthOptions = {
|
|
920
938
|
consumer: {
|
|
@@ -928,7 +946,7 @@ class App {
|
|
|
928
946
|
},
|
|
929
947
|
};
|
|
930
948
|
const oauthRequestData = {
|
|
931
|
-
oauth_callback: `${_1.WebhookHelpers.getWebhookBaseUrl()}${this.restEndpoint}/oauth1-credential/callback?cid=${
|
|
949
|
+
oauth_callback: `${_1.WebhookHelpers.getWebhookBaseUrl()}${this.restEndpoint}/oauth1-credential/callback?cid=${credentialId}`,
|
|
932
950
|
};
|
|
933
951
|
await this.externalHooks.run('oauth1.authenticate', [oAuthOptions, oauthRequestData]);
|
|
934
952
|
const oauth = new clientOAuth1(oAuthOptions);
|
|
@@ -942,35 +960,46 @@ class App {
|
|
|
942
960
|
const response = await requestPromise(options);
|
|
943
961
|
const responseJson = querystring.parse(response);
|
|
944
962
|
const returnUri = `${_.get(oauthCredentials, 'authUrl')}?oauth_token=${responseJson.oauth_token}`;
|
|
945
|
-
const credentials = new n8n_core_1.Credentials(
|
|
963
|
+
const credentials = new n8n_core_1.Credentials(credential, credential.type, credential.nodesAccess);
|
|
946
964
|
credentials.setData(decryptedDataOriginal, encryptionKey);
|
|
947
965
|
const newCredentialsData = credentials.getDataToSave();
|
|
948
966
|
newCredentialsData.updatedAt = this.getCurrentDate();
|
|
949
|
-
await _1.Db.collections.Credentials.update(
|
|
967
|
+
await _1.Db.collections.Credentials.update(credentialId, newCredentialsData);
|
|
968
|
+
n8n_workflow_1.LoggerProxy.verbose('OAuth1 authorization successful for new credential', {
|
|
969
|
+
userId: req.user.id,
|
|
970
|
+
credentialId,
|
|
971
|
+
});
|
|
950
972
|
return returnUri;
|
|
951
973
|
}));
|
|
952
974
|
this.app.get(`/${this.restEndpoint}/oauth1-credential/callback`, async (req, res) => {
|
|
953
975
|
try {
|
|
954
|
-
const { oauth_verifier, oauth_token, cid } = req.query;
|
|
955
|
-
if (oauth_verifier
|
|
976
|
+
const { oauth_verifier, oauth_token, cid: credentialId } = req.query;
|
|
977
|
+
if (!oauth_verifier || !oauth_token) {
|
|
956
978
|
const errorResponse = new _1.ResponseHelper.ResponseError(`Insufficient parameters for OAuth1 callback. Received following query parameters: ${JSON.stringify(req.query)}`, undefined, 503);
|
|
979
|
+
n8n_workflow_1.LoggerProxy.error('OAuth1 callback failed because of insufficient parameters received', {
|
|
980
|
+
userId: req.user.id,
|
|
981
|
+
credentialId,
|
|
982
|
+
});
|
|
957
983
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
958
984
|
}
|
|
959
|
-
const
|
|
960
|
-
if (
|
|
961
|
-
|
|
985
|
+
const credential = await _1.getCredentialForUser(credentialId, req.user);
|
|
986
|
+
if (!credential) {
|
|
987
|
+
n8n_workflow_1.LoggerProxy.error('OAuth1 callback failed because of insufficient user permissions', {
|
|
988
|
+
userId: req.user.id,
|
|
989
|
+
credentialId,
|
|
990
|
+
});
|
|
991
|
+
const errorResponse = new _1.ResponseHelper.ResponseError(constants_1.RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL, undefined, 404);
|
|
962
992
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
963
993
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
const errorResponse = new _1.ResponseHelper.ResponseError('No encryption key got found to decrypt the credentials!', undefined, 503);
|
|
994
|
+
const encryptionKey = await n8n_core_1.UserSettings.getEncryptionKey();
|
|
995
|
+
if (!encryptionKey) {
|
|
996
|
+
const errorResponse = new _1.ResponseHelper.ResponseError(constants_1.RESPONSE_ERROR_MESSAGES.NO_ENCRYPTION_KEY, undefined, 503);
|
|
968
997
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
969
998
|
}
|
|
970
999
|
const mode = 'internal';
|
|
971
1000
|
const credentialsHelper = new _1.CredentialsHelper(encryptionKey);
|
|
972
|
-
const decryptedDataOriginal = await credentialsHelper.getDecrypted(
|
|
973
|
-
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal,
|
|
1001
|
+
const decryptedDataOriginal = await credentialsHelper.getDecrypted(credential, credential.type, mode, true);
|
|
1002
|
+
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal, credential.type, mode);
|
|
974
1003
|
const options = {
|
|
975
1004
|
method: 'POST',
|
|
976
1005
|
url: _.get(oauthCredentials, 'accessTokenUrl'),
|
|
@@ -984,42 +1013,55 @@ class App {
|
|
|
984
1013
|
oauthToken = await requestPromise(options);
|
|
985
1014
|
}
|
|
986
1015
|
catch (error) {
|
|
1016
|
+
n8n_workflow_1.LoggerProxy.error('Unable to fetch tokens for OAuth1 callback', {
|
|
1017
|
+
userId: req.user.id,
|
|
1018
|
+
credentialId,
|
|
1019
|
+
});
|
|
987
1020
|
const errorResponse = new _1.ResponseHelper.ResponseError('Unable to get access tokens!', undefined, 404);
|
|
988
1021
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
989
1022
|
}
|
|
990
1023
|
const oauthTokenJson = querystring.parse(oauthToken);
|
|
991
1024
|
decryptedDataOriginal.oauthTokenData = oauthTokenJson;
|
|
992
|
-
const credentials = new n8n_core_1.Credentials(
|
|
1025
|
+
const credentials = new n8n_core_1.Credentials(credential, credential.type, credential.nodesAccess);
|
|
993
1026
|
credentials.setData(decryptedDataOriginal, encryptionKey);
|
|
994
1027
|
const newCredentialsData = credentials.getDataToSave();
|
|
995
1028
|
newCredentialsData.updatedAt = this.getCurrentDate();
|
|
996
|
-
await _1.Db.collections.Credentials.update(
|
|
1029
|
+
await _1.Db.collections.Credentials.update(credentialId, newCredentialsData);
|
|
1030
|
+
n8n_workflow_1.LoggerProxy.verbose('OAuth1 callback successful for new credential', {
|
|
1031
|
+
userId: req.user.id,
|
|
1032
|
+
credentialId,
|
|
1033
|
+
});
|
|
997
1034
|
res.sendFile(path_1.resolve(__dirname, '../../templates/oauth-callback.html'));
|
|
998
1035
|
}
|
|
999
1036
|
catch (error) {
|
|
1037
|
+
n8n_workflow_1.LoggerProxy.error('OAuth1 callback failed because of insufficient user permissions', {
|
|
1038
|
+
userId: req.user.id,
|
|
1039
|
+
credentialId: req.query.cid,
|
|
1040
|
+
});
|
|
1000
1041
|
return _1.ResponseHelper.sendErrorResponse(res, error);
|
|
1001
1042
|
}
|
|
1002
1043
|
});
|
|
1003
|
-
this.app.get(`/${this.restEndpoint}/oauth2-credential/auth`, _1.ResponseHelper.send(async (req
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
}
|
|
1008
|
-
const
|
|
1009
|
-
if (
|
|
1010
|
-
|
|
1011
|
-
|
|
1044
|
+
this.app.get(`/${this.restEndpoint}/oauth2-credential/auth`, _1.ResponseHelper.send(async (req) => {
|
|
1045
|
+
const { id: credentialId } = req.query;
|
|
1046
|
+
if (!credentialId) {
|
|
1047
|
+
throw new _1.ResponseHelper.ResponseError('Required credential ID is missing', undefined, 400);
|
|
1048
|
+
}
|
|
1049
|
+
const credential = await _1.getCredentialForUser(credentialId, req.user);
|
|
1050
|
+
if (!credential) {
|
|
1051
|
+
n8n_workflow_1.LoggerProxy.error('Failed to authorize OAuth2 due to lack of permissions', {
|
|
1052
|
+
userId: req.user.id,
|
|
1053
|
+
credentialId,
|
|
1054
|
+
});
|
|
1055
|
+
throw new _1.ResponseHelper.ResponseError(constants_1.RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL, undefined, 404);
|
|
1012
1056
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
res.status(500).send('No encryption key got found to decrypt the credentials!');
|
|
1017
|
-
return '';
|
|
1057
|
+
const encryptionKey = await n8n_core_1.UserSettings.getEncryptionKey();
|
|
1058
|
+
if (!encryptionKey) {
|
|
1059
|
+
throw new _1.ResponseHelper.ResponseError(constants_1.RESPONSE_ERROR_MESSAGES.NO_ENCRYPTION_KEY, undefined, 500);
|
|
1018
1060
|
}
|
|
1019
1061
|
const mode = 'internal';
|
|
1020
1062
|
const credentialsHelper = new _1.CredentialsHelper(encryptionKey);
|
|
1021
|
-
const decryptedDataOriginal = await credentialsHelper.getDecrypted(
|
|
1022
|
-
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal,
|
|
1063
|
+
const decryptedDataOriginal = await credentialsHelper.getDecrypted(credential, credential.type, mode, true);
|
|
1064
|
+
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal, credential.type, mode);
|
|
1023
1065
|
const token = new csrf();
|
|
1024
1066
|
const csrfSecret = token.secretSync();
|
|
1025
1067
|
const state = {
|
|
@@ -1038,7 +1080,7 @@ class App {
|
|
|
1038
1080
|
};
|
|
1039
1081
|
await this.externalHooks.run('oauth2.authenticate', [oAuthOptions]);
|
|
1040
1082
|
const oAuthObj = new clientOAuth2(oAuthOptions);
|
|
1041
|
-
const credentials = new n8n_core_1.Credentials(
|
|
1083
|
+
const credentials = new n8n_core_1.Credentials(credential, credential.type, credential.nodesAccess);
|
|
1042
1084
|
decryptedDataOriginal.csrfSecret = csrfSecret;
|
|
1043
1085
|
credentials.setData(decryptedDataOriginal, encryptionKey);
|
|
1044
1086
|
const newCredentialsData = credentials.getDataToSave();
|
|
@@ -1054,12 +1096,16 @@ class App {
|
|
|
1054
1096
|
if (authQueryParameters) {
|
|
1055
1097
|
returnUri += `&${authQueryParameters}`;
|
|
1056
1098
|
}
|
|
1099
|
+
n8n_workflow_1.LoggerProxy.verbose('OAuth2 authentication successful for new credential', {
|
|
1100
|
+
userId: req.user.id,
|
|
1101
|
+
credentialId,
|
|
1102
|
+
});
|
|
1057
1103
|
return returnUri;
|
|
1058
1104
|
}));
|
|
1059
1105
|
this.app.get(`/${this.restEndpoint}/oauth2-credential/callback`, async (req, res) => {
|
|
1060
1106
|
try {
|
|
1061
1107
|
const { code, state: stateEncoded } = req.query;
|
|
1062
|
-
if (code
|
|
1108
|
+
if (!code || !stateEncoded) {
|
|
1063
1109
|
const errorResponse = new _1.ResponseHelper.ResponseError(`Insufficient parameters for OAuth2 callback. Received following query parameters: ${JSON.stringify(req.query)}`, undefined, 503);
|
|
1064
1110
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
1065
1111
|
}
|
|
@@ -1071,24 +1117,31 @@ class App {
|
|
|
1071
1117
|
const errorResponse = new _1.ResponseHelper.ResponseError('Invalid state format returned', undefined, 503);
|
|
1072
1118
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
1073
1119
|
}
|
|
1074
|
-
const
|
|
1075
|
-
if (
|
|
1076
|
-
|
|
1120
|
+
const credential = await _1.getCredentialForUser(state.cid, req.user);
|
|
1121
|
+
if (!credential) {
|
|
1122
|
+
n8n_workflow_1.LoggerProxy.error('OAuth2 callback failed because of insufficient permissions', {
|
|
1123
|
+
userId: req.user.id,
|
|
1124
|
+
credentialId: state.cid,
|
|
1125
|
+
});
|
|
1126
|
+
const errorResponse = new _1.ResponseHelper.ResponseError(constants_1.RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL, undefined, 404);
|
|
1077
1127
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
1078
1128
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
const errorResponse = new _1.ResponseHelper.ResponseError('No encryption key got found to decrypt the credentials!', undefined, 503);
|
|
1129
|
+
const encryptionKey = await n8n_core_1.UserSettings.getEncryptionKey();
|
|
1130
|
+
if (!encryptionKey) {
|
|
1131
|
+
const errorResponse = new _1.ResponseHelper.ResponseError(constants_1.RESPONSE_ERROR_MESSAGES.NO_ENCRYPTION_KEY, undefined, 503);
|
|
1083
1132
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
1084
1133
|
}
|
|
1085
1134
|
const mode = 'internal';
|
|
1086
1135
|
const credentialsHelper = new _1.CredentialsHelper(encryptionKey);
|
|
1087
|
-
const decryptedDataOriginal = await credentialsHelper.getDecrypted(
|
|
1088
|
-
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal,
|
|
1136
|
+
const decryptedDataOriginal = await credentialsHelper.getDecrypted(credential, credential.type, mode, true);
|
|
1137
|
+
const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites(decryptedDataOriginal, credential.type, mode);
|
|
1089
1138
|
const token = new csrf();
|
|
1090
1139
|
if (decryptedDataOriginal.csrfSecret === undefined ||
|
|
1091
1140
|
!token.verify(decryptedDataOriginal.csrfSecret, state.token)) {
|
|
1141
|
+
n8n_workflow_1.LoggerProxy.debug('OAuth2 callback state is invalid', {
|
|
1142
|
+
userId: req.user.id,
|
|
1143
|
+
credentialId: state.cid,
|
|
1144
|
+
});
|
|
1092
1145
|
const errorResponse = new _1.ResponseHelper.ResponseError('The OAuth2 callback state is invalid!', undefined, 404);
|
|
1093
1146
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
1094
1147
|
}
|
|
@@ -1118,6 +1171,10 @@ class App {
|
|
|
1118
1171
|
_.set(oauthToken.data, 'callbackQueryString', _.omit(req.query, 'state', 'code'));
|
|
1119
1172
|
}
|
|
1120
1173
|
if (oauthToken === undefined) {
|
|
1174
|
+
n8n_workflow_1.LoggerProxy.error('OAuth2 callback failed: unable to get access tokens', {
|
|
1175
|
+
userId: req.user.id,
|
|
1176
|
+
credentialId: state.cid,
|
|
1177
|
+
});
|
|
1121
1178
|
const errorResponse = new _1.ResponseHelper.ResponseError('Unable to get access tokens!', undefined, 404);
|
|
1122
1179
|
return _1.ResponseHelper.sendErrorResponse(res, errorResponse);
|
|
1123
1180
|
}
|
|
@@ -1128,124 +1185,152 @@ class App {
|
|
|
1128
1185
|
decryptedDataOriginal.oauthTokenData = oauthToken.data;
|
|
1129
1186
|
}
|
|
1130
1187
|
_.unset(decryptedDataOriginal, 'csrfSecret');
|
|
1131
|
-
const credentials = new n8n_core_1.Credentials(
|
|
1188
|
+
const credentials = new n8n_core_1.Credentials(credential, credential.type, credential.nodesAccess);
|
|
1132
1189
|
credentials.setData(decryptedDataOriginal, encryptionKey);
|
|
1133
1190
|
const newCredentialsData = credentials.getDataToSave();
|
|
1134
1191
|
newCredentialsData.updatedAt = this.getCurrentDate();
|
|
1135
1192
|
await _1.Db.collections.Credentials.update(state.cid, newCredentialsData);
|
|
1193
|
+
n8n_workflow_1.LoggerProxy.verbose('OAuth2 callback successful for new credential', {
|
|
1194
|
+
userId: req.user.id,
|
|
1195
|
+
credentialId: state.cid,
|
|
1196
|
+
});
|
|
1136
1197
|
res.sendFile(path_1.resolve(__dirname, '../../templates/oauth-callback.html'));
|
|
1137
1198
|
}
|
|
1138
1199
|
catch (error) {
|
|
1139
1200
|
return _1.ResponseHelper.sendErrorResponse(res, error);
|
|
1140
1201
|
}
|
|
1141
1202
|
});
|
|
1142
|
-
this.app.get(`/${this.restEndpoint}/executions`, _1.ResponseHelper.send(async (req
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
let limit = 20;
|
|
1148
|
-
if (req.query.limit) {
|
|
1149
|
-
limit = parseInt(req.query.limit, 10);
|
|
1150
|
-
}
|
|
1203
|
+
this.app.get(`/${this.restEndpoint}/executions`, _1.ResponseHelper.send(async (req) => {
|
|
1204
|
+
const filter = req.query.filter ? JSON.parse(req.query.filter) : {};
|
|
1205
|
+
const limit = req.query.limit
|
|
1206
|
+
? parseInt(req.query.limit, 10)
|
|
1207
|
+
: GenericHelpers_1.DEFAULT_EXECUTIONS_GET_ALL_LIMIT;
|
|
1151
1208
|
const executingWorkflowIds = [];
|
|
1152
1209
|
if (config.get('executions.mode') === 'queue') {
|
|
1153
1210
|
const currentJobs = await Queue.getInstance().getJobs(['active', 'waiting']);
|
|
1154
|
-
executingWorkflowIds.push(...currentJobs.map((
|
|
1155
|
-
}
|
|
1156
|
-
executingWorkflowIds.push(...this.activeExecutionsInstance
|
|
1157
|
-
.getActiveExecutions()
|
|
1158
|
-
.map((execution) => execution.id.toString()));
|
|
1159
|
-
const countFilter = JSON.parse(JSON.stringify(filter));
|
|
1160
|
-
if (countFilter.waitTill !== undefined) {
|
|
1161
|
-
countFilter.waitTill = typeorm_1.Not(typeorm_1.IsNull());
|
|
1211
|
+
executingWorkflowIds.push(...currentJobs.map(({ data }) => data.executionId));
|
|
1162
1212
|
}
|
|
1213
|
+
executingWorkflowIds.push(...this.activeExecutionsInstance.getActiveExecutions().map(({ id }) => id));
|
|
1214
|
+
const countFilter = lodash_1.cloneDeep(filter);
|
|
1215
|
+
countFilter.waitTill && (countFilter.waitTill = typeorm_1.Not(typeorm_1.IsNull()));
|
|
1163
1216
|
countFilter.id = typeorm_1.Not(typeorm_1.In(executingWorkflowIds));
|
|
1164
|
-
const
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
.
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1217
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(req.user);
|
|
1218
|
+
const findOptions = {
|
|
1219
|
+
select: [
|
|
1220
|
+
'id',
|
|
1221
|
+
'finished',
|
|
1222
|
+
'mode',
|
|
1223
|
+
'retryOf',
|
|
1224
|
+
'retrySuccessId',
|
|
1225
|
+
'waitTill',
|
|
1226
|
+
'startedAt',
|
|
1227
|
+
'stoppedAt',
|
|
1228
|
+
'workflowData',
|
|
1229
|
+
],
|
|
1230
|
+
where: { workflowId: typeorm_1.In(sharedWorkflowIds) },
|
|
1231
|
+
order: { id: 'DESC' },
|
|
1232
|
+
take: limit,
|
|
1233
|
+
};
|
|
1234
|
+
Object.entries(filter).forEach(([key, value]) => {
|
|
1235
|
+
let filterToAdd = {};
|
|
1236
|
+
if (key === 'waitTill') {
|
|
1237
|
+
filterToAdd = { waitTill: !typeorm_1.IsNull() };
|
|
1238
|
+
}
|
|
1239
|
+
else if (key === 'finished' && value === false) {
|
|
1240
|
+
filterToAdd = { finished: false, waitTill: typeorm_1.IsNull() };
|
|
1188
1241
|
}
|
|
1189
1242
|
else {
|
|
1190
|
-
|
|
1191
|
-
[filterField]: filter[filterField],
|
|
1192
|
-
});
|
|
1243
|
+
filterToAdd = { [key]: value };
|
|
1193
1244
|
}
|
|
1245
|
+
Object.assign(findOptions.where, filterToAdd);
|
|
1194
1246
|
});
|
|
1247
|
+
const rangeQuery = [];
|
|
1248
|
+
const rangeQueryParams = {};
|
|
1195
1249
|
if (req.query.lastId) {
|
|
1196
|
-
|
|
1250
|
+
rangeQuery.push('id < :lastId');
|
|
1251
|
+
rangeQueryParams.lastId = req.query.lastId;
|
|
1197
1252
|
}
|
|
1198
1253
|
if (req.query.firstId) {
|
|
1199
|
-
|
|
1254
|
+
rangeQuery.push('id > :firstId');
|
|
1255
|
+
rangeQueryParams.firstId = req.query.firstId;
|
|
1200
1256
|
}
|
|
1201
1257
|
if (executingWorkflowIds.length > 0) {
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
const returnResults = [];
|
|
1209
|
-
for (const result of results) {
|
|
1210
|
-
returnResults.push({
|
|
1211
|
-
id: result.id.toString(),
|
|
1212
|
-
finished: result.finished,
|
|
1213
|
-
mode: result.mode,
|
|
1214
|
-
retryOf: result.retryOf ? result.retryOf.toString() : undefined,
|
|
1215
|
-
retrySuccessId: result.retrySuccessId ? result.retrySuccessId.toString() : undefined,
|
|
1216
|
-
waitTill: result.waitTill,
|
|
1217
|
-
startedAt: result.startedAt,
|
|
1218
|
-
stoppedAt: result.stoppedAt,
|
|
1219
|
-
workflowId: result.workflowData.id ? result.workflowData.id.toString() : '',
|
|
1220
|
-
workflowName: result.workflowData.name,
|
|
1258
|
+
rangeQuery.push(`id NOT IN (:...executingWorkflowIds)`);
|
|
1259
|
+
rangeQueryParams.executingWorkflowIds = executingWorkflowIds;
|
|
1260
|
+
}
|
|
1261
|
+
if (rangeQuery.length) {
|
|
1262
|
+
Object.assign(findOptions.where, {
|
|
1263
|
+
id: typeorm_1.Raw(() => rangeQuery.join(' and '), rangeQueryParams),
|
|
1221
1264
|
});
|
|
1222
1265
|
}
|
|
1266
|
+
const executions = await _1.Db.collections.Execution.find(findOptions);
|
|
1267
|
+
const { count, estimated } = await getExecutionsCount(countFilter, req.user);
|
|
1268
|
+
const formattedExecutions = executions.map((execution) => {
|
|
1269
|
+
var _a, _b, _c, _d, _e;
|
|
1270
|
+
return {
|
|
1271
|
+
id: execution.id.toString(),
|
|
1272
|
+
finished: execution.finished,
|
|
1273
|
+
mode: execution.mode,
|
|
1274
|
+
retryOf: (_a = execution.retryOf) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
1275
|
+
retrySuccessId: (_b = execution === null || execution === void 0 ? void 0 : execution.retrySuccessId) === null || _b === void 0 ? void 0 : _b.toString(),
|
|
1276
|
+
waitTill: execution.waitTill,
|
|
1277
|
+
startedAt: execution.startedAt,
|
|
1278
|
+
stoppedAt: execution.stoppedAt,
|
|
1279
|
+
workflowId: (_e = (_d = (_c = execution.workflowData) === null || _c === void 0 ? void 0 : _c.id) === null || _d === void 0 ? void 0 : _d.toString()) !== null && _e !== void 0 ? _e : '',
|
|
1280
|
+
workflowName: execution.workflowData.name,
|
|
1281
|
+
};
|
|
1282
|
+
});
|
|
1223
1283
|
return {
|
|
1224
|
-
count
|
|
1225
|
-
results:
|
|
1226
|
-
estimated
|
|
1284
|
+
count,
|
|
1285
|
+
results: formattedExecutions,
|
|
1286
|
+
estimated,
|
|
1227
1287
|
};
|
|
1228
1288
|
}));
|
|
1229
|
-
this.app.get(`/${this.restEndpoint}/executions/:id`, _1.ResponseHelper.send(async (req
|
|
1230
|
-
const
|
|
1231
|
-
|
|
1289
|
+
this.app.get(`/${this.restEndpoint}/executions/:id`, _1.ResponseHelper.send(async (req) => {
|
|
1290
|
+
const { id: executionId } = req.params;
|
|
1291
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(req.user);
|
|
1292
|
+
if (!sharedWorkflowIds.length)
|
|
1293
|
+
return undefined;
|
|
1294
|
+
const execution = await _1.Db.collections.Execution.findOne({
|
|
1295
|
+
where: {
|
|
1296
|
+
id: executionId,
|
|
1297
|
+
workflowId: typeorm_1.In(sharedWorkflowIds),
|
|
1298
|
+
},
|
|
1299
|
+
});
|
|
1300
|
+
if (!execution) {
|
|
1301
|
+
n8n_workflow_1.LoggerProxy.info('Attempt to read execution was blocked due to insufficient permissions', {
|
|
1302
|
+
userId: req.user.id,
|
|
1303
|
+
executionId,
|
|
1304
|
+
});
|
|
1232
1305
|
return undefined;
|
|
1233
1306
|
}
|
|
1234
1307
|
if (req.query.unflattedResponse === 'true') {
|
|
1235
|
-
|
|
1236
|
-
return fullExecutionData;
|
|
1308
|
+
return _1.ResponseHelper.unflattenExecutionData(execution);
|
|
1237
1309
|
}
|
|
1238
|
-
|
|
1239
|
-
return
|
|
1310
|
+
const { id } = execution, rest = __rest(execution, ["id"]);
|
|
1311
|
+
return Object.assign({ id: id.toString() }, rest);
|
|
1240
1312
|
}));
|
|
1241
|
-
this.app.post(`/${this.restEndpoint}/executions/:id/retry`, _1.ResponseHelper.send(async (req
|
|
1242
|
-
const
|
|
1243
|
-
|
|
1244
|
-
|
|
1313
|
+
this.app.post(`/${this.restEndpoint}/executions/:id/retry`, _1.ResponseHelper.send(async (req) => {
|
|
1314
|
+
const { id: executionId } = req.params;
|
|
1315
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(req.user);
|
|
1316
|
+
if (!sharedWorkflowIds.length)
|
|
1317
|
+
return false;
|
|
1318
|
+
const execution = await _1.Db.collections.Execution.findOne({
|
|
1319
|
+
where: {
|
|
1320
|
+
id: executionId,
|
|
1321
|
+
workflowId: typeorm_1.In(sharedWorkflowIds),
|
|
1322
|
+
},
|
|
1323
|
+
});
|
|
1324
|
+
if (!execution) {
|
|
1325
|
+
n8n_workflow_1.LoggerProxy.info('Attempt to retry an execution was blocked due to insufficient permissions', {
|
|
1326
|
+
userId: req.user.id,
|
|
1327
|
+
executionId,
|
|
1328
|
+
});
|
|
1329
|
+
throw new _1.ResponseHelper.ResponseError(`The execution with the ID "${executionId}" does not exist.`, 404, 404);
|
|
1245
1330
|
}
|
|
1246
|
-
const fullExecutionData = _1.ResponseHelper.unflattenExecutionData(
|
|
1331
|
+
const fullExecutionData = _1.ResponseHelper.unflattenExecutionData(execution);
|
|
1247
1332
|
if (fullExecutionData.finished) {
|
|
1248
|
-
throw new Error('The execution
|
|
1333
|
+
throw new Error('The execution succeeded, so it cannot be retried.');
|
|
1249
1334
|
}
|
|
1250
1335
|
const executionMode = 'retry';
|
|
1251
1336
|
fullExecutionData.workflowData.active = false;
|
|
@@ -1254,6 +1339,7 @@ class App {
|
|
|
1254
1339
|
executionData: fullExecutionData.data,
|
|
1255
1340
|
retryOf: req.params.id,
|
|
1256
1341
|
workflowData: fullExecutionData.workflowData,
|
|
1342
|
+
userId: req.user.id,
|
|
1257
1343
|
};
|
|
1258
1344
|
const { lastNodeExecuted } = data.executionData.resultData;
|
|
1259
1345
|
if (lastNodeExecuted) {
|
|
@@ -1264,7 +1350,7 @@ class App {
|
|
|
1264
1350
|
data.executionData.resultData.runData[lastNodeExecuted].pop();
|
|
1265
1351
|
}
|
|
1266
1352
|
}
|
|
1267
|
-
if (req.body.loadWorkflow
|
|
1353
|
+
if (req.body.loadWorkflow) {
|
|
1268
1354
|
const workflowId = fullExecutionData.workflowData.id;
|
|
1269
1355
|
const workflowData = (await _1.Db.collections.Workflow.findOne(workflowId));
|
|
1270
1356
|
if (workflowData === undefined) {
|
|
@@ -1285,88 +1371,115 @@ class App {
|
|
|
1285
1371
|
for (const stack of data.executionData.executionData.nodeExecutionStack) {
|
|
1286
1372
|
const node = workflowInstance.getNode(stack.node.name);
|
|
1287
1373
|
if (node === null) {
|
|
1374
|
+
n8n_workflow_1.LoggerProxy.error('Failed to retry an execution because a node could not be found', {
|
|
1375
|
+
userId: req.user.id,
|
|
1376
|
+
executionId,
|
|
1377
|
+
nodeName: stack.node.name,
|
|
1378
|
+
});
|
|
1288
1379
|
throw new Error(`Could not find the node "${stack.node.name}" in workflow. It probably got deleted or renamed. Without it the workflow can sadly not be retried.`);
|
|
1289
1380
|
}
|
|
1290
1381
|
stack.node = node;
|
|
1291
1382
|
}
|
|
1292
1383
|
}
|
|
1293
1384
|
const workflowRunner = new _1.WorkflowRunner();
|
|
1294
|
-
const
|
|
1295
|
-
const executionData = await this.activeExecutionsInstance.getPostExecutePromise(
|
|
1296
|
-
if (executionData
|
|
1385
|
+
const retriedExecutionId = await workflowRunner.run(data);
|
|
1386
|
+
const executionData = await this.activeExecutionsInstance.getPostExecutePromise(retriedExecutionId);
|
|
1387
|
+
if (!executionData) {
|
|
1297
1388
|
throw new Error('The retry did not start for an unknown reason.');
|
|
1298
1389
|
}
|
|
1299
1390
|
return !!executionData.finished;
|
|
1300
1391
|
}));
|
|
1301
|
-
this.app.post(`/${this.restEndpoint}/executions/delete`, _1.ResponseHelper.send(async (req
|
|
1302
|
-
const
|
|
1303
|
-
if (
|
|
1392
|
+
this.app.post(`/${this.restEndpoint}/executions/delete`, _1.ResponseHelper.send(async (req) => {
|
|
1393
|
+
const { deleteBefore, ids, filters: requestFilters } = req.body;
|
|
1394
|
+
if (!deleteBefore && !ids) {
|
|
1395
|
+
throw new Error('Either "deleteBefore" or "ids" must be present in the request body');
|
|
1396
|
+
}
|
|
1397
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(req.user);
|
|
1398
|
+
const binaryDataManager = n8n_core_1.BinaryDataManager.getInstance();
|
|
1399
|
+
if (deleteBefore) {
|
|
1304
1400
|
const filters = {
|
|
1305
|
-
startedAt: typeorm_1.LessThanOrEqual(
|
|
1401
|
+
startedAt: typeorm_1.LessThanOrEqual(deleteBefore),
|
|
1306
1402
|
};
|
|
1307
|
-
if (
|
|
1308
|
-
Object.assign(filters,
|
|
1403
|
+
if (filters) {
|
|
1404
|
+
Object.assign(filters, requestFilters);
|
|
1309
1405
|
}
|
|
1310
|
-
const
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
await
|
|
1406
|
+
const executions = await _1.Db.collections.Execution.find({
|
|
1407
|
+
where: Object.assign({ workflowId: typeorm_1.In(sharedWorkflowIds) }, filters),
|
|
1408
|
+
});
|
|
1409
|
+
if (!executions.length)
|
|
1410
|
+
return;
|
|
1411
|
+
const idsToDelete = executions.map(({ id }) => id.toString());
|
|
1412
|
+
await Promise.all(idsToDelete.map(async (id) => binaryDataManager.deleteBinaryDataByExecutionId(id)));
|
|
1413
|
+
await _1.Db.collections.Execution.delete({ id: typeorm_1.In(idsToDelete) });
|
|
1414
|
+
return;
|
|
1317
1415
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1416
|
+
if (ids) {
|
|
1417
|
+
const executions = await _1.Db.collections.Execution.find({
|
|
1418
|
+
where: {
|
|
1419
|
+
id: typeorm_1.In(ids),
|
|
1420
|
+
workflowId: typeorm_1.In(sharedWorkflowIds),
|
|
1421
|
+
},
|
|
1422
|
+
});
|
|
1423
|
+
if (!executions.length) {
|
|
1424
|
+
n8n_workflow_1.LoggerProxy.error('Failed to delete an execution due to insufficient permissions', {
|
|
1425
|
+
userId: req.user.id,
|
|
1426
|
+
executionIds: ids,
|
|
1427
|
+
});
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
const idsToDelete = executions.map(({ id }) => id.toString());
|
|
1431
|
+
await Promise.all(idsToDelete.map(async (id) => binaryDataManager.deleteBinaryDataByExecutionId(id)));
|
|
1432
|
+
await _1.Db.collections.Execution.delete(idsToDelete);
|
|
1320
1433
|
}
|
|
1321
1434
|
}));
|
|
1322
|
-
this.app.get(`/${this.restEndpoint}/executions-current`, _1.ResponseHelper.send(async (req
|
|
1435
|
+
this.app.get(`/${this.restEndpoint}/executions-current`, _1.ResponseHelper.send(async (req) => {
|
|
1323
1436
|
if (config.get('executions.mode') === 'queue') {
|
|
1324
1437
|
const currentJobs = await Queue.getInstance().getJobs(['active', 'waiting']);
|
|
1325
1438
|
const currentlyRunningQueueIds = currentJobs.map((job) => job.data.executionId);
|
|
1326
1439
|
const currentlyRunningManualExecutions = this.activeExecutionsInstance.getActiveExecutions();
|
|
1327
1440
|
const manualExecutionIds = currentlyRunningManualExecutions.map((execution) => execution.id);
|
|
1328
1441
|
const currentlyRunningExecutionIds = currentlyRunningQueueIds.concat(manualExecutionIds);
|
|
1329
|
-
if (currentlyRunningExecutionIds.length
|
|
1442
|
+
if (!currentlyRunningExecutionIds.length)
|
|
1443
|
+
return [];
|
|
1444
|
+
const findOptions = {
|
|
1445
|
+
select: ['id', 'workflowId', 'mode', 'retryOf', 'startedAt'],
|
|
1446
|
+
order: { id: 'DESC' },
|
|
1447
|
+
where: {
|
|
1448
|
+
id: typeorm_1.In(currentlyRunningExecutionIds),
|
|
1449
|
+
},
|
|
1450
|
+
};
|
|
1451
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(req.user);
|
|
1452
|
+
if (!sharedWorkflowIds.length)
|
|
1330
1453
|
return [];
|
|
1331
|
-
}
|
|
1332
|
-
const resultsQuery = await _1.Db.collections
|
|
1333
|
-
.Execution.createQueryBuilder('execution')
|
|
1334
|
-
.select([
|
|
1335
|
-
'execution.id',
|
|
1336
|
-
'execution.workflowId',
|
|
1337
|
-
'execution.mode',
|
|
1338
|
-
'execution.retryOf',
|
|
1339
|
-
'execution.startedAt',
|
|
1340
|
-
])
|
|
1341
|
-
.orderBy('execution.id', 'DESC')
|
|
1342
|
-
.andWhere(`execution.id IN (:...ids)`, { ids: currentlyRunningExecutionIds });
|
|
1343
1454
|
if (req.query.filter) {
|
|
1344
|
-
const
|
|
1345
|
-
if (
|
|
1346
|
-
|
|
1347
|
-
workflowId: filter.workflowId,
|
|
1348
|
-
});
|
|
1455
|
+
const { workflowId } = JSON.parse(req.query.filter);
|
|
1456
|
+
if (workflowId && sharedWorkflowIds.includes(workflowId)) {
|
|
1457
|
+
Object.assign(findOptions.where, { workflowId });
|
|
1349
1458
|
}
|
|
1350
1459
|
}
|
|
1351
|
-
|
|
1352
|
-
|
|
1460
|
+
else {
|
|
1461
|
+
Object.assign(findOptions.where, { workflowId: typeorm_1.In(sharedWorkflowIds) });
|
|
1462
|
+
}
|
|
1463
|
+
const executions = await _1.Db.collections.Execution.find(findOptions);
|
|
1464
|
+
if (!executions.length)
|
|
1465
|
+
return [];
|
|
1466
|
+
return executions.map((execution) => {
|
|
1353
1467
|
return {
|
|
1354
|
-
id:
|
|
1355
|
-
workflowId:
|
|
1356
|
-
mode:
|
|
1357
|
-
retryOf:
|
|
1358
|
-
startedAt: new Date(
|
|
1468
|
+
id: execution.id,
|
|
1469
|
+
workflowId: execution.workflowId,
|
|
1470
|
+
mode: execution.mode,
|
|
1471
|
+
retryOf: execution.retryOf !== null ? execution.retryOf : undefined,
|
|
1472
|
+
startedAt: new Date(execution.startedAt),
|
|
1359
1473
|
};
|
|
1360
1474
|
});
|
|
1361
1475
|
}
|
|
1362
1476
|
const executingWorkflows = this.activeExecutionsInstance.getActiveExecutions();
|
|
1363
1477
|
const returnData = [];
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
filter = JSON.parse(req.query.filter);
|
|
1367
|
-
}
|
|
1478
|
+
const filter = req.query.filter ? JSON.parse(req.query.filter) : {};
|
|
1479
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(req.user).then((ids) => ids.map((id) => id.toString()));
|
|
1368
1480
|
for (const data of executingWorkflows) {
|
|
1369
|
-
if (filter.workflowId !== undefined && filter.workflowId !== data.workflowId)
|
|
1481
|
+
if ((filter.workflowId !== undefined && filter.workflowId !== data.workflowId) ||
|
|
1482
|
+
!sharedWorkflowIds.includes(data.workflowId)) {
|
|
1370
1483
|
continue;
|
|
1371
1484
|
}
|
|
1372
1485
|
returnData.push({
|
|
@@ -1380,8 +1493,22 @@ class App {
|
|
|
1380
1493
|
returnData.sort((a, b) => parseInt(b.id, 10) - parseInt(a.id, 10));
|
|
1381
1494
|
return returnData;
|
|
1382
1495
|
}));
|
|
1383
|
-
this.app.post(`/${this.restEndpoint}/executions-current/:id/stop`, _1.ResponseHelper.send(async (req
|
|
1496
|
+
this.app.post(`/${this.restEndpoint}/executions-current/:id/stop`, _1.ResponseHelper.send(async (req) => {
|
|
1384
1497
|
var _a;
|
|
1498
|
+
const { id: executionId } = req.params;
|
|
1499
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(req.user);
|
|
1500
|
+
if (!sharedWorkflowIds.length) {
|
|
1501
|
+
throw new _1.ResponseHelper.ResponseError('Execution not found', undefined, 404);
|
|
1502
|
+
}
|
|
1503
|
+
const execution = await _1.Db.collections.Execution.findOne({
|
|
1504
|
+
where: {
|
|
1505
|
+
id: executionId,
|
|
1506
|
+
workflowId: typeorm_1.In(sharedWorkflowIds),
|
|
1507
|
+
},
|
|
1508
|
+
});
|
|
1509
|
+
if (!execution) {
|
|
1510
|
+
throw new _1.ResponseHelper.ResponseError('Execution not found', undefined, 404);
|
|
1511
|
+
}
|
|
1385
1512
|
if (config.get('executions.mode') === 'queue') {
|
|
1386
1513
|
const result = await this.activeExecutionsInstance.stopExecution(req.params.id);
|
|
1387
1514
|
if (result === undefined) {
|
|
@@ -1419,7 +1546,6 @@ class App {
|
|
|
1419
1546
|
};
|
|
1420
1547
|
return returnData;
|
|
1421
1548
|
}
|
|
1422
|
-
const executionId = req.params.id;
|
|
1423
1549
|
const result = await this.activeExecutionsInstance.stopExecution(executionId);
|
|
1424
1550
|
let returnData;
|
|
1425
1551
|
if (result === undefined) {
|
|
@@ -1451,19 +1577,8 @@ class App {
|
|
|
1451
1577
|
});
|
|
1452
1578
|
}));
|
|
1453
1579
|
this.app.get(`/${this.restEndpoint}/settings`, _1.ResponseHelper.send(async (req, res) => {
|
|
1454
|
-
return this.
|
|
1580
|
+
return this.getSettingsForFrontend();
|
|
1455
1581
|
}));
|
|
1456
|
-
this.app.post(`/${this.restEndpoint}/user-survey`, async (req, res) => {
|
|
1457
|
-
if (!this.frontendSettings.personalizationSurvey.shouldShow) {
|
|
1458
|
-
_1.ResponseHelper.sendErrorResponse(res, new _1.ResponseHelper.ResponseError('User survey already submitted', undefined, 400), false);
|
|
1459
|
-
}
|
|
1460
|
-
const answers = req.body;
|
|
1461
|
-
await PersonalizationSurvey.writeSurveyToDisk(answers);
|
|
1462
|
-
this.frontendSettings.personalizationSurvey.shouldShow = false;
|
|
1463
|
-
this.frontendSettings.personalizationSurvey.answers = answers;
|
|
1464
|
-
_1.ResponseHelper.sendSuccessResponse(res, undefined, true, 200);
|
|
1465
|
-
void InternalHooksManager_1.InternalHooksManager.getInstance().onPersonalizationSurveySubmitted(answers);
|
|
1466
|
-
});
|
|
1467
1582
|
if (config.get('endpoints.disableProductionWebhooksOnMainProcess') !== true) {
|
|
1468
1583
|
_1.WebhookServer.registerProductionWebhooks.apply(this);
|
|
1469
1584
|
}
|
|
@@ -1602,6 +1717,9 @@ async function start() {
|
|
|
1602
1717
|
},
|
|
1603
1718
|
deploymentType: config.get('deployment.type'),
|
|
1604
1719
|
binaryDataMode: binarDataConfig.mode,
|
|
1720
|
+
n8n_multi_user_allowed: config.get('userManagement.disabled') === false ||
|
|
1721
|
+
config.get('userManagement.isInstanceOwnerSetUp') === true,
|
|
1722
|
+
smtp_set_up: config.get('userManagement.emails.mode') === 'smtp',
|
|
1605
1723
|
};
|
|
1606
1724
|
void _1.Db.collections
|
|
1607
1725
|
.Workflow.findOne({
|
|
@@ -1618,25 +1736,33 @@ async function start() {
|
|
|
1618
1736
|
});
|
|
1619
1737
|
}
|
|
1620
1738
|
exports.start = start;
|
|
1621
|
-
async function getExecutionsCount(countFilter) {
|
|
1739
|
+
async function getExecutionsCount(countFilter, user) {
|
|
1622
1740
|
const dbType = (await _1.GenericHelpers.getConfigValue('database.type'));
|
|
1623
1741
|
const filteredFields = Object.keys(countFilter).filter((field) => field !== 'id');
|
|
1624
|
-
if (dbType !== 'postgresdb' || filteredFields.length > 0) {
|
|
1625
|
-
const
|
|
1626
|
-
|
|
1742
|
+
if (dbType !== 'postgresdb' || filteredFields.length > 0 || user.globalRole.name !== 'owner') {
|
|
1743
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(user);
|
|
1744
|
+
const count = await _1.Db.collections.Execution.count({
|
|
1745
|
+
where: Object.assign({ workflowId: typeorm_1.In(sharedWorkflowIds) }, countFilter),
|
|
1746
|
+
});
|
|
1747
|
+
return { count, estimated: false };
|
|
1627
1748
|
}
|
|
1628
1749
|
try {
|
|
1629
1750
|
const estimateRowsNumberSql = "SELECT n_live_tup FROM pg_stat_all_tables WHERE relname = 'execution_entity';";
|
|
1630
1751
|
const rows = await _1.Db.collections.Execution.query(estimateRowsNumberSql);
|
|
1631
1752
|
const estimate = parseInt(rows[0].n_live_tup, 10);
|
|
1632
1753
|
if (estimate > 100000) {
|
|
1633
|
-
return { count: estimate,
|
|
1754
|
+
return { count: estimate, estimated: true };
|
|
1634
1755
|
}
|
|
1635
1756
|
}
|
|
1636
|
-
catch (
|
|
1637
|
-
n8n_workflow_1.LoggerProxy.warn(`
|
|
1757
|
+
catch (error) {
|
|
1758
|
+
n8n_workflow_1.LoggerProxy.warn(`Failed to get executions count from Postgres: ${error}`);
|
|
1638
1759
|
}
|
|
1639
|
-
const
|
|
1640
|
-
|
|
1760
|
+
const sharedWorkflowIds = await WorkflowHelpers_1.getSharedWorkflowIds(user);
|
|
1761
|
+
const count = await _1.Db.collections.Execution.count({
|
|
1762
|
+
where: {
|
|
1763
|
+
workflowId: typeorm_1.In(sharedWorkflowIds),
|
|
1764
|
+
},
|
|
1765
|
+
});
|
|
1766
|
+
return { count, estimated: false };
|
|
1641
1767
|
}
|
|
1642
1768
|
//# sourceMappingURL=Server.js.map
|