n8n 0.167.0 → 0.168.2

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