n8n 0.167.0 → 0.168.0

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