@atom8n/n8n 2.4.7 → 2.5.1

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 (231) hide show
  1. package/dist/build.tsbuildinfo +1 -1
  2. package/dist/chat/chat-service.types.d.ts +6 -6
  3. package/dist/commands/execute-batch.d.ts +2 -2
  4. package/dist/commands/execute.js +0 -0
  5. package/dist/commands/import/credentials.d.ts +2 -2
  6. package/dist/commands/import/credentials.js +0 -0
  7. package/dist/commands/import/workflow.d.ts +2 -2
  8. package/dist/commands/ldap/reset.d.ts +2 -2
  9. package/dist/commands/mcp.d.ts +23 -0
  10. package/dist/commands/mcp.js +315 -0
  11. package/dist/commands/run.d.ts +23 -0
  12. package/dist/commands/run.js +162 -0
  13. package/dist/controllers/annotation-tags.controller.ee.d.ts +1 -1
  14. package/dist/controllers/cli.controller.d.ts +26 -0
  15. package/dist/controllers/cli.controller.js +334 -0
  16. package/dist/controllers/orchestration.controller.js +0 -0
  17. package/dist/controllers/users.controller.d.ts +1 -1
  18. package/dist/environments.ee/source-control/source-control-status.service.ee.d.ts +2 -2
  19. package/dist/environments.ee/source-control/source-control.controller.ee.d.ts +4 -4
  20. package/dist/environments.ee/source-control/source-control.service.ee.d.ts +2 -2
  21. package/dist/environments.ee/source-control/types/source-control-set-branch.js +0 -0
  22. package/dist/eventbus/event-message-classes/index.js +0 -0
  23. package/dist/events/relays/workflow-failure-notification.event-relay.d.ts +13 -0
  24. package/dist/events/relays/workflow-failure-notification.event-relay.js +77 -0
  25. package/dist/executions/execution-data/types.d.ts +17 -0
  26. package/dist/executions/execution-data/types.js +2 -0
  27. package/dist/executions/failed-run-factory.d.ts +4 -0
  28. package/dist/executions/failed-run-factory.js +71 -0
  29. package/dist/index.d.ts +2 -1
  30. package/dist/index.js +8 -0
  31. package/dist/interfaces.d.ts +1 -1
  32. package/dist/license.js +1 -1
  33. package/dist/middlewares/webview-frame-options.d.ts +2 -0
  34. package/dist/middlewares/webview-frame-options.js +22 -0
  35. package/dist/modules/chat-hub/chat-hub-extractor.d.ts +22 -0
  36. package/dist/modules/chat-hub/chat-hub-extractor.js +63 -0
  37. package/dist/modules/dynamic-credentials.ee/credential-resolvers/storage/dynamic-credential-user-entry-storage.d.ts +11 -0
  38. package/dist/modules/dynamic-credentials.ee/credential-resolvers/storage/dynamic-credential-user-entry-storage.js +58 -0
  39. package/dist/modules/dynamic-credentials.ee/database/entities/dynamic-credential-user-entry.d.ts +12 -0
  40. package/dist/modules/dynamic-credentials.ee/database/entities/dynamic-credential-user-entry.js +64 -0
  41. package/dist/modules/dynamic-credentials.ee/database/repositories/dynamic-credential-user-entry.repository.d.ts +5 -0
  42. package/dist/modules/dynamic-credentials.ee/database/repositories/dynamic-credential-user-entry.repository.js +25 -0
  43. package/dist/modules/dynamic-credentials.ee/dynamic-credentials.config.d.ts +5 -0
  44. package/dist/modules/dynamic-credentials.ee/dynamic-credentials.config.js +36 -0
  45. package/dist/modules/dynamic-credentials.ee/services/dynamic-credential-cors.service.d.ts +12 -0
  46. package/dist/modules/dynamic-credentials.ee/services/dynamic-credential-cors.service.js +69 -0
  47. package/dist/modules/dynamic-credentials.ee/services/resolver-config-expression.service.d.ts +7 -0
  48. package/dist/modules/dynamic-credentials.ee/services/resolver-config-expression.service.js +46 -0
  49. package/dist/modules/insights/database/entities/insights-metadata.js +1 -1
  50. package/dist/modules/insights/database/repositories/insights-by-period-query.helper.js +4 -1
  51. package/dist/modules/insights/database/repositories/insights-by-period.repository.d.ts +1 -1
  52. package/dist/modules/insights/insights.module.d.ts +1 -1
  53. package/dist/modules/insights/insights.service.d.ts +1 -1
  54. package/dist/modules/log-streaming.ee/database/entities/event-destination.entity.d.ts +6 -0
  55. package/dist/modules/log-streaming.ee/database/entities/event-destination.entity.js +28 -0
  56. package/dist/modules/log-streaming.ee/database/entities/index.d.ts +1 -0
  57. package/dist/modules/log-streaming.ee/database/entities/index.js +5 -0
  58. package/dist/modules/log-streaming.ee/database/repositories/event-destination.repository.d.ts +5 -0
  59. package/dist/modules/log-streaming.ee/database/repositories/event-destination.repository.js +25 -0
  60. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination-from-db.d.ts +4 -0
  61. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination-from-db.js +24 -0
  62. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination-sentry.ee.d.ts +17 -0
  63. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination-sentry.ee.js +131 -0
  64. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination-syslog.ee.d.ts +22 -0
  65. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination-syslog.ee.js +116 -0
  66. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination-webhook.ee.d.ts +35 -0
  67. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination-webhook.ee.js +328 -0
  68. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination.ee.d.ts +28 -0
  69. package/dist/modules/log-streaming.ee/destinations/message-event-bus-destination.ee.js +74 -0
  70. package/dist/modules/log-streaming.ee/log-streaming-destination.service.d.ts +32 -0
  71. package/dist/modules/log-streaming.ee/log-streaming-destination.service.js +175 -0
  72. package/dist/modules/log-streaming.ee/log-streaming.controller.d.ts +15 -0
  73. package/dist/modules/log-streaming.ee/log-streaming.controller.js +149 -0
  74. package/dist/modules/log-streaming.ee/log-streaming.module.d.ts +5 -0
  75. package/dist/modules/log-streaming.ee/log-streaming.module.js +66 -0
  76. package/dist/modules/mcp/mcp-oauth.helpers.js +0 -0
  77. package/dist/modules/mcp/mcp.oauth-clients.controller.js +0 -0
  78. package/dist/modules/mcp/tools/execute-workflow.tool.d.ts +10 -10
  79. package/dist/modules/mcp/tools/schemas.d.ts +10 -10
  80. package/dist/modules/source-control.ee/constants.d.ts +17 -0
  81. package/dist/modules/source-control.ee/constants.js +22 -0
  82. package/dist/modules/source-control.ee/middleware/source-control-enabled-middleware.ee.d.ts +2 -0
  83. package/dist/modules/source-control.ee/middleware/source-control-enabled-middleware.ee.js +18 -0
  84. package/dist/modules/source-control.ee/source-control-export.service.ee.d.ts +37 -0
  85. package/dist/modules/source-control.ee/source-control-export.service.ee.js +426 -0
  86. package/dist/modules/source-control.ee/source-control-git.service.ee.d.ts +59 -0
  87. package/dist/modules/source-control.ee/source-control-git.service.ee.js +427 -0
  88. package/dist/modules/source-control.ee/source-control-helper.ee.d.ts +49 -0
  89. package/dist/modules/source-control.ee/source-control-helper.ee.js +241 -0
  90. package/dist/modules/source-control.ee/source-control-import.service.ee.d.ts +110 -0
  91. package/dist/modules/source-control.ee/source-control-import.service.ee.js +957 -0
  92. package/dist/modules/source-control.ee/source-control-preferences.service.ee.d.ts +46 -0
  93. package/dist/modules/source-control.ee/source-control-preferences.service.ee.js +309 -0
  94. package/dist/modules/source-control.ee/source-control-resource-helper.d.ts +4 -0
  95. package/dist/modules/source-control.ee/source-control-resource-helper.js +20 -0
  96. package/dist/modules/source-control.ee/source-control-scoped.service.d.ts +17 -0
  97. package/dist/modules/source-control.ee/source-control-scoped.service.js +134 -0
  98. package/dist/modules/source-control.ee/source-control-status.service.ee.d.ts +90 -0
  99. package/dist/modules/source-control.ee/source-control-status.service.ee.js +596 -0
  100. package/dist/modules/source-control.ee/source-control.config.d.ts +3 -0
  101. package/dist/modules/source-control.ee/source-control.config.js +26 -0
  102. package/dist/modules/source-control.ee/source-control.controller.ee.d.ts +157 -0
  103. package/dist/modules/source-control.ee/source-control.controller.ee.js +347 -0
  104. package/dist/modules/source-control.ee/source-control.module.d.ts +4 -0
  105. package/dist/modules/source-control.ee/source-control.module.js +59 -0
  106. package/dist/modules/source-control.ee/source-control.service.ee.d.ts +125 -0
  107. package/dist/modules/source-control.ee/source-control.service.ee.js +466 -0
  108. package/dist/modules/source-control.ee/types/export-result.d.ts +10 -0
  109. package/dist/modules/source-control.ee/types/export-result.js +2 -0
  110. package/dist/modules/source-control.ee/types/exportable-credential.d.ts +14 -0
  111. package/dist/modules/source-control.ee/types/exportable-credential.js +2 -0
  112. package/dist/modules/source-control.ee/types/exportable-folders.d.ts +11 -0
  113. package/dist/modules/source-control.ee/types/exportable-folders.js +2 -0
  114. package/dist/modules/source-control.ee/types/exportable-project.d.ts +17 -0
  115. package/dist/modules/source-control.ee/types/exportable-project.js +2 -0
  116. package/dist/modules/source-control.ee/types/exportable-tags.d.ts +5 -0
  117. package/dist/modules/source-control.ee/types/exportable-tags.js +2 -0
  118. package/dist/modules/source-control.ee/types/exportable-variable.d.ts +7 -0
  119. package/dist/modules/source-control.ee/types/exportable-variable.js +2 -0
  120. package/dist/modules/source-control.ee/types/exportable-workflow.d.ts +14 -0
  121. package/dist/modules/source-control.ee/types/exportable-workflow.js +2 -0
  122. package/dist/modules/source-control.ee/types/import-result.d.ts +20 -0
  123. package/dist/modules/source-control.ee/types/import-result.js +2 -0
  124. package/dist/modules/source-control.ee/types/key-pair-type.d.ts +1 -0
  125. package/dist/modules/source-control.ee/types/key-pair-type.js +2 -0
  126. package/dist/modules/source-control.ee/types/key-pair.d.ts +4 -0
  127. package/dist/modules/source-control.ee/types/key-pair.js +2 -0
  128. package/dist/modules/source-control.ee/types/requests.d.ts +21 -0
  129. package/dist/modules/source-control.ee/types/requests.js +2 -0
  130. package/dist/modules/source-control.ee/types/resource-owner.d.ts +17 -0
  131. package/dist/modules/source-control.ee/types/resource-owner.js +2 -0
  132. package/dist/modules/source-control.ee/types/source-control-commit.d.ts +3 -0
  133. package/dist/modules/source-control.ee/types/source-control-commit.js +20 -0
  134. package/dist/modules/source-control.ee/types/source-control-context.d.ts +7 -0
  135. package/dist/modules/source-control.ee/types/source-control-context.js +16 -0
  136. package/dist/modules/source-control.ee/types/source-control-disconnect.d.ts +3 -0
  137. package/dist/modules/source-control.ee/types/source-control-disconnect.js +21 -0
  138. package/dist/modules/source-control.ee/types/source-control-generate-key-pair.d.ts +4 -0
  139. package/dist/modules/source-control.ee/types/source-control-generate-key-pair.js +21 -0
  140. package/dist/modules/source-control.ee/types/source-control-get-status.d.ts +10 -0
  141. package/dist/modules/source-control.ee/types/source-control-get-status.js +42 -0
  142. package/dist/modules/source-control.ee/types/source-control-preferences.d.ts +17 -0
  143. package/dist/modules/source-control.ee/types/source-control-preferences.js +88 -0
  144. package/dist/modules/source-control.ee/types/source-control-push.d.ts +3 -0
  145. package/dist/modules/source-control.ee/types/source-control-push.js +21 -0
  146. package/dist/modules/source-control.ee/types/source-control-set-branch.d.ts +3 -0
  147. package/dist/modules/source-control.ee/types/source-control-set-branch.js +20 -0
  148. package/dist/modules/source-control.ee/types/source-control-set-read-only.d.ts +3 -0
  149. package/dist/modules/source-control.ee/types/source-control-set-read-only.js +20 -0
  150. package/dist/modules/source-control.ee/types/source-control-stage.d.ts +5 -0
  151. package/dist/modules/source-control.ee/types/source-control-stage.js +31 -0
  152. package/dist/modules/source-control.ee/types/source-control-workflow-version-id.d.ts +12 -0
  153. package/dist/modules/source-control.ee/types/source-control-workflow-version-id.js +2 -0
  154. package/dist/modules/sso-oidc/constants.d.ts +3 -0
  155. package/dist/modules/sso-oidc/constants.js +6 -0
  156. package/dist/modules/sso-oidc/oidc.controller.ee.d.ts +23 -0
  157. package/dist/modules/sso-oidc/oidc.controller.ee.js +123 -0
  158. package/dist/modules/sso-oidc/oidc.service.ee.d.ts +56 -0
  159. package/dist/modules/sso-oidc/oidc.service.ee.js +468 -0
  160. package/dist/modules/sso-oidc/sso-oidc.module.d.ts +4 -0
  161. package/dist/modules/sso-oidc/sso-oidc.module.js +55 -0
  162. package/dist/modules/sso-saml/constants.d.ts +3 -0
  163. package/dist/modules/sso-saml/constants.js +6 -0
  164. package/dist/modules/sso-saml/errors/invalid-saml-metadata-url.error.d.ts +4 -0
  165. package/dist/modules/sso-saml/errors/invalid-saml-metadata-url.error.js +10 -0
  166. package/dist/modules/sso-saml/errors/invalid-saml-metadata.error.d.ts +4 -0
  167. package/dist/modules/sso-saml/errors/invalid-saml-metadata.error.js +10 -0
  168. package/dist/modules/sso-saml/middleware/saml-enabled-middleware.d.ts +3 -0
  169. package/dist/modules/sso-saml/middleware/saml-enabled-middleware.js +22 -0
  170. package/dist/modules/sso-saml/saml-helpers.d.ts +19 -0
  171. package/dist/modules/sso-saml/saml-helpers.js +129 -0
  172. package/dist/modules/sso-saml/saml-validator.d.ts +16 -0
  173. package/dist/modules/sso-saml/saml-validator.js +129 -0
  174. package/dist/modules/sso-saml/saml.controller.ee.d.ts +50 -0
  175. package/dist/modules/sso-saml/saml.controller.ee.js +227 -0
  176. package/dist/modules/sso-saml/saml.service.ee.d.ts +52 -0
  177. package/dist/modules/sso-saml/saml.service.ee.js +462 -0
  178. package/dist/modules/sso-saml/schema/metadata-exchange.xsd.d.ts +2 -0
  179. package/dist/modules/sso-saml/schema/metadata-exchange.xsd.js +118 -0
  180. package/dist/modules/sso-saml/schema/oasis-200401-wss-wssecurity-secext-1.0.xsd.d.ts +2 -0
  181. package/dist/modules/sso-saml/schema/oasis-200401-wss-wssecurity-secext-1.0.xsd.js +201 -0
  182. package/dist/modules/sso-saml/schema/oasis-200401-wss-wssecurity-utility-1.0.xsd.d.ts +2 -0
  183. package/dist/modules/sso-saml/schema/oasis-200401-wss-wssecurity-utility-1.0.xsd.js +114 -0
  184. package/dist/modules/sso-saml/schema/saml-schema-assertion-2.0.xsd.d.ts +2 -0
  185. package/dist/modules/sso-saml/schema/saml-schema-assertion-2.0.xsd.js +289 -0
  186. package/dist/modules/sso-saml/schema/saml-schema-metadata-2.0.xsd.d.ts +2 -0
  187. package/dist/modules/sso-saml/schema/saml-schema-metadata-2.0.xsd.js +344 -0
  188. package/dist/modules/sso-saml/schema/saml-schema-protocol-2.0.xsd.d.ts +2 -0
  189. package/dist/modules/sso-saml/schema/saml-schema-protocol-2.0.xsd.js +308 -0
  190. package/dist/modules/sso-saml/schema/ws-addr.xsd.d.ts +2 -0
  191. package/dist/modules/sso-saml/schema/ws-addr.xsd.js +143 -0
  192. package/dist/modules/sso-saml/schema/ws-authorization.xsd.d.ts +2 -0
  193. package/dist/modules/sso-saml/schema/ws-authorization.xsd.js +151 -0
  194. package/dist/modules/sso-saml/schema/ws-federation.xsd.d.ts +2 -0
  195. package/dist/modules/sso-saml/schema/ws-federation.xsd.js +476 -0
  196. package/dist/modules/sso-saml/schema/ws-securitypolicy-1.2.xsd.d.ts +2 -0
  197. package/dist/modules/sso-saml/schema/ws-securitypolicy-1.2.xsd.js +1211 -0
  198. package/dist/modules/sso-saml/schema/xenc-schema.xsd.d.ts +2 -0
  199. package/dist/modules/sso-saml/schema/xenc-schema.xsd.js +151 -0
  200. package/dist/modules/sso-saml/schema/xml.xsd.d.ts +2 -0
  201. package/dist/modules/sso-saml/schema/xml.xsd.js +123 -0
  202. package/dist/modules/sso-saml/schema/xmldsig-core-schema.xsd.d.ts +2 -0
  203. package/dist/modules/sso-saml/schema/xmldsig-core-schema.xsd.js +324 -0
  204. package/dist/modules/sso-saml/service-provider.ee.d.ts +6 -0
  205. package/dist/modules/sso-saml/service-provider.ee.js +44 -0
  206. package/dist/modules/sso-saml/sso-saml.module.d.ts +4 -0
  207. package/dist/modules/sso-saml/sso-saml.module.js +55 -0
  208. package/dist/modules/sso-saml/types.d.ts +4 -0
  209. package/dist/modules/sso-saml/types.js +2 -0
  210. package/dist/modules/sso-saml/views/init-sso-post.d.ts +2 -0
  211. package/dist/modules/sso-saml/views/init-sso-post.js +16 -0
  212. package/dist/node-lib.d.ts +10 -0
  213. package/dist/node-lib.js +137 -0
  214. package/dist/push/index.d.ts +1 -1
  215. package/dist/server.d.ts +1 -0
  216. package/dist/server.js +1 -0
  217. package/dist/services/cors-service.d.ts +7 -0
  218. package/dist/services/cors-service.js +50 -0
  219. package/dist/services/static-auth-service.d.ts +4 -0
  220. package/dist/services/static-auth-service.js +29 -0
  221. package/dist/sso.ee/saml/schema/metadata-exchange.xsd.js +0 -0
  222. package/dist/task-runners/task-broker/errors/task-runner-accept-timeout.error.js +0 -0
  223. package/dist/typecheck.tsbuildinfo +1 -0
  224. package/dist/user-management/email/templates/workflow-failure.handlebars +211 -0
  225. package/dist/utils/cors.util.d.ts +2 -0
  226. package/dist/utils/cors.util.js +17 -0
  227. package/dist/webhooks/waiting-forms.js +3 -3
  228. package/dist/webhooks/waiting-webhooks.js +2 -0
  229. package/dist/workflows/workflow.service.d.ts +2 -2
  230. package/dist/workflows/workflows.controller.d.ts +6 -6
  231. package/package.json +22 -21
@@ -0,0 +1,462 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.SamlService = void 0;
49
+ const backend_common_1 = require("@n8n/backend-common");
50
+ const config_1 = require("@n8n/config");
51
+ const db_1 = require("@n8n/db");
52
+ const decorators_1 = require("@n8n/decorators");
53
+ const di_1 = require("@n8n/di");
54
+ const axios_1 = __importDefault(require("axios"));
55
+ const n8n_core_1 = require("n8n-core");
56
+ const n8n_workflow_1 = require("n8n-workflow");
57
+ const auth_error_1 = require("../../errors/response-errors/auth.error");
58
+ const bad_request_error_1 = require("../../errors/response-errors/bad-request.error");
59
+ const provisioning_service_ee_1 = require("../../modules/provisioning.ee/provisioning.service.ee");
60
+ const url_service_1 = require("../../services/url.service");
61
+ const sso_helpers_1 = require("../../sso.ee/sso-helpers");
62
+ const constants_1 = require("./constants");
63
+ const invalid_saml_metadata_url_error_1 = require("./errors/invalid-saml-metadata-url.error");
64
+ const invalid_saml_metadata_error_1 = require("./errors/invalid-saml-metadata.error");
65
+ const saml_helpers_1 = require("./saml-helpers");
66
+ const saml_validator_1 = require("./saml-validator");
67
+ const service_provider_ee_1 = require("./service-provider.ee");
68
+ let SamlService = class SamlService {
69
+ get samlPreferences() {
70
+ return {
71
+ ...this._samlPreferences,
72
+ loginEnabled: (0, sso_helpers_1.isSamlLoginEnabled)(),
73
+ loginLabel: (0, sso_helpers_1.getSamlLoginLabel)(),
74
+ };
75
+ }
76
+ constructor(logger, urlService, validator, userRepository, settingsRepository, instanceSettings, provisioningService) {
77
+ this.logger = logger;
78
+ this.urlService = urlService;
79
+ this.validator = validator;
80
+ this.userRepository = userRepository;
81
+ this.settingsRepository = settingsRepository;
82
+ this.instanceSettings = instanceSettings;
83
+ this.provisioningService = provisioningService;
84
+ this._samlPreferences = {
85
+ mapping: {
86
+ email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
87
+ firstName: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/firstname',
88
+ lastName: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/lastname',
89
+ userPrincipalName: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn',
90
+ },
91
+ metadata: '',
92
+ metadataUrl: '',
93
+ ignoreSSL: false,
94
+ loginBinding: 'redirect',
95
+ acsBinding: 'post',
96
+ authnRequestsSigned: false,
97
+ loginEnabled: false,
98
+ loginLabel: 'SAML',
99
+ wantAssertionsSigned: true,
100
+ wantMessageSigned: true,
101
+ relayState: this.urlService.getInstanceBaseUrl(),
102
+ signatureConfig: {
103
+ prefix: 'ds',
104
+ location: {
105
+ reference: '/samlp:Response/saml:Issuer',
106
+ action: 'after',
107
+ },
108
+ },
109
+ };
110
+ this.isReloading = false;
111
+ }
112
+ async init() {
113
+ try {
114
+ await this.loadFromDbAndApplySamlPreferences(false);
115
+ await this.validator.init();
116
+ if ((0, sso_helpers_1.isSamlLicensedAndEnabled)()) {
117
+ await this.loadSamlify();
118
+ await this.loadFromDbAndApplySamlPreferences(true);
119
+ }
120
+ }
121
+ catch (error) {
122
+ if (error instanceof invalid_saml_metadata_url_error_1.InvalidSamlMetadataUrlError ||
123
+ error instanceof invalid_saml_metadata_error_1.InvalidSamlMetadataError ||
124
+ error instanceof SyntaxError) {
125
+ this.logger.warn(`SAML initialization failed because of invalid metadata in database: ${error.message}. IMPORTANT: Disabling SAML and switching to email-based login for all users. Please review your configuration and re-enable SAML.`);
126
+ await this.reset();
127
+ }
128
+ else {
129
+ throw error;
130
+ }
131
+ }
132
+ }
133
+ async loadSamlify() {
134
+ if (this.samlify === undefined) {
135
+ this.logger.debug('Loading samlify library into memory');
136
+ this.samlify = await Promise.resolve().then(() => __importStar(require('samlify')));
137
+ }
138
+ this.samlify.setSchemaValidator({
139
+ validate: async (response) => {
140
+ const valid = await this.validator.validateResponse(response);
141
+ if (!valid) {
142
+ throw new invalid_saml_metadata_error_1.InvalidSamlMetadataError();
143
+ }
144
+ },
145
+ });
146
+ }
147
+ getIdentityProviderInstance(forceRecreate = false) {
148
+ if (this.samlify === undefined) {
149
+ throw new n8n_workflow_1.UnexpectedError('Samlify is not initialized');
150
+ }
151
+ if (this.identityProviderInstance === undefined || forceRecreate) {
152
+ this.identityProviderInstance = this.samlify.IdentityProvider({
153
+ metadata: this._samlPreferences.metadata,
154
+ });
155
+ }
156
+ this.validator.validateIdentiyProvider(this.identityProviderInstance);
157
+ return this.identityProviderInstance;
158
+ }
159
+ getServiceProviderInstance() {
160
+ if (this.samlify === undefined) {
161
+ throw new n8n_workflow_1.UnexpectedError('Samlify is not initialized');
162
+ }
163
+ return (0, service_provider_ee_1.getServiceProviderInstance)(this._samlPreferences, this.samlify);
164
+ }
165
+ async getLoginRequestUrl(relayState, binding) {
166
+ await this.loadSamlify();
167
+ if (binding === undefined)
168
+ binding = this._samlPreferences.loginBinding ?? 'redirect';
169
+ if (binding === 'post') {
170
+ return {
171
+ binding,
172
+ context: this.getPostLoginRequestUrl(relayState),
173
+ };
174
+ }
175
+ else {
176
+ return {
177
+ binding,
178
+ context: this.getRedirectLoginRequestUrl(relayState),
179
+ };
180
+ }
181
+ }
182
+ getRedirectLoginRequestUrl(relayState) {
183
+ const sp = this.getServiceProviderInstance();
184
+ sp.entitySetting.relayState = relayState ?? this.urlService.getInstanceBaseUrl();
185
+ const loginRequest = sp.createLoginRequest(this.getIdentityProviderInstance(), 'redirect');
186
+ return loginRequest;
187
+ }
188
+ getPostLoginRequestUrl(relayState) {
189
+ const sp = this.getServiceProviderInstance();
190
+ sp.entitySetting.relayState = relayState ?? this.urlService.getInstanceBaseUrl();
191
+ const loginRequest = sp.createLoginRequest(this.getIdentityProviderInstance(), 'post');
192
+ return loginRequest;
193
+ }
194
+ async handleSamlLogin(req, binding) {
195
+ const attributes = await this.getAttributesFromLoginResponse(req, binding);
196
+ if (attributes.email) {
197
+ const lowerCasedEmail = attributes.email.toLowerCase();
198
+ if (!(0, db_1.isValidEmail)(lowerCasedEmail)) {
199
+ throw new bad_request_error_1.BadRequestError('Invalid email format');
200
+ }
201
+ const user = await this.userRepository.findOne({
202
+ where: { email: lowerCasedEmail },
203
+ relations: ['authIdentities', 'role'],
204
+ });
205
+ if (user) {
206
+ if (user.authIdentities.find((e) => e.providerType === 'saml' && e.providerId === attributes.userPrincipalName)) {
207
+ await this.applySsoProvisioning(user, attributes);
208
+ return {
209
+ authenticatedUser: user,
210
+ attributes,
211
+ onboardingRequired: false,
212
+ };
213
+ }
214
+ else {
215
+ const updatedUser = await (0, saml_helpers_1.updateUserFromSamlAttributes)(user, attributes);
216
+ const onboardingRequired = !updatedUser.firstName || !updatedUser.lastName;
217
+ await this.applySsoProvisioning(updatedUser, attributes);
218
+ return {
219
+ authenticatedUser: updatedUser,
220
+ attributes,
221
+ onboardingRequired,
222
+ };
223
+ }
224
+ }
225
+ else {
226
+ if ((0, sso_helpers_1.isSsoJustInTimeProvisioningEnabled)()) {
227
+ const newUser = await (0, saml_helpers_1.createUserFromSamlAttributes)(attributes);
228
+ await this.applySsoProvisioning(newUser, attributes);
229
+ return {
230
+ authenticatedUser: newUser,
231
+ attributes,
232
+ onboardingRequired: true,
233
+ };
234
+ }
235
+ }
236
+ }
237
+ return {
238
+ authenticatedUser: undefined,
239
+ attributes,
240
+ onboardingRequired: false,
241
+ };
242
+ }
243
+ async applySsoProvisioning(user, attributes) {
244
+ if (attributes?.n8nInstanceRole) {
245
+ await this.provisioningService.provisionInstanceRoleForUser(user, attributes.n8nInstanceRole);
246
+ }
247
+ if (attributes?.n8nProjectRoles) {
248
+ await this.provisioningService.provisionProjectRolesForUser(user.id, attributes.n8nProjectRoles);
249
+ }
250
+ }
251
+ async broadcastReloadSAMLConfigurationCommand() {
252
+ if (this.instanceSettings.isMultiMain) {
253
+ const { Publisher } = await Promise.resolve().then(() => __importStar(require('../../scaling/pubsub/publisher.service')));
254
+ await di_1.Container.get(Publisher).publishCommand({ command: 'reload-saml-config' });
255
+ }
256
+ }
257
+ async reload() {
258
+ if (this.isReloading) {
259
+ this.logger.warn('SAML configuration reload already in progress');
260
+ return;
261
+ }
262
+ this.isReloading = true;
263
+ try {
264
+ this.logger.debug('SAML configuration changed, starting to load it from the database');
265
+ await this.loadFromDbAndApplySamlPreferences(true, false);
266
+ await (0, sso_helpers_1.reloadAuthenticationMethod)();
267
+ const samlLoginEnabled = (0, sso_helpers_1.isSamlLoginEnabled)();
268
+ this.logger.debug(`SAML login is now ${samlLoginEnabled ? 'enabled' : 'disabled'}.`);
269
+ di_1.Container.get(config_1.GlobalConfig).sso.saml.loginEnabled = samlLoginEnabled;
270
+ }
271
+ catch (error) {
272
+ this.logger.error('SAML configuration changed, failed to reload SAML configuration', {
273
+ error,
274
+ });
275
+ }
276
+ finally {
277
+ this.isReloading = false;
278
+ }
279
+ }
280
+ async setSamlPreferences(prefs, tryFallback = false, broadcastReload = true) {
281
+ await this.loadSamlify();
282
+ const previousMetadataUrl = this._samlPreferences.metadataUrl;
283
+ await this.loadPreferencesWithoutValidation(prefs);
284
+ if (prefs.metadataUrl) {
285
+ try {
286
+ const fetchedMetadata = await this.fetchMetadataFromUrl();
287
+ if (fetchedMetadata) {
288
+ this._samlPreferences.metadata = fetchedMetadata;
289
+ }
290
+ else {
291
+ throw new invalid_saml_metadata_url_error_1.InvalidSamlMetadataUrlError(prefs.metadataUrl);
292
+ }
293
+ }
294
+ catch (error) {
295
+ this._samlPreferences.metadataUrl = previousMetadataUrl;
296
+ if (!tryFallback) {
297
+ throw error;
298
+ }
299
+ this.logger.error('SAML initialization detected an invalid metadata URL in database. Trying to initialize from metadata in database if available.', { error });
300
+ }
301
+ }
302
+ else if (prefs.metadata) {
303
+ const validationResult = await this.validator.validateMetadata(prefs.metadata);
304
+ if (!validationResult) {
305
+ throw new invalid_saml_metadata_error_1.InvalidSamlMetadataError();
306
+ }
307
+ }
308
+ if ((0, sso_helpers_1.isSamlLoginEnabled)()) {
309
+ if (this._samlPreferences.metadata) {
310
+ const validationResult = await this.validator.validateMetadata(this._samlPreferences.metadata);
311
+ if (!validationResult) {
312
+ throw new invalid_saml_metadata_error_1.InvalidSamlMetadataError();
313
+ }
314
+ }
315
+ else {
316
+ throw new invalid_saml_metadata_error_1.InvalidSamlMetadataError();
317
+ }
318
+ }
319
+ this.getIdentityProviderInstance(true);
320
+ const result = await this.saveSamlPreferencesToDb();
321
+ if (broadcastReload) {
322
+ await this.broadcastReloadSAMLConfigurationCommand();
323
+ }
324
+ return result;
325
+ }
326
+ async loadPreferencesWithoutValidation(prefs) {
327
+ this._samlPreferences.loginBinding = prefs.loginBinding ?? this._samlPreferences.loginBinding;
328
+ this._samlPreferences.metadata = prefs.metadata ?? this._samlPreferences.metadata;
329
+ this._samlPreferences.mapping = prefs.mapping ?? this._samlPreferences.mapping;
330
+ this._samlPreferences.ignoreSSL = prefs.ignoreSSL ?? this._samlPreferences.ignoreSSL;
331
+ this._samlPreferences.acsBinding = prefs.acsBinding ?? this._samlPreferences.acsBinding;
332
+ this._samlPreferences.signatureConfig =
333
+ prefs.signatureConfig ?? this._samlPreferences.signatureConfig;
334
+ this._samlPreferences.authnRequestsSigned =
335
+ prefs.authnRequestsSigned ?? this._samlPreferences.authnRequestsSigned;
336
+ this._samlPreferences.wantAssertionsSigned =
337
+ prefs.wantAssertionsSigned ?? this._samlPreferences.wantAssertionsSigned;
338
+ this._samlPreferences.wantMessageSigned =
339
+ prefs.wantMessageSigned ?? this._samlPreferences.wantMessageSigned;
340
+ if (prefs.metadataUrl) {
341
+ this._samlPreferences.metadataUrl = prefs.metadataUrl;
342
+ }
343
+ else if (prefs.metadata) {
344
+ this._samlPreferences.metadataUrl = undefined;
345
+ this._samlPreferences.metadata = prefs.metadata;
346
+ }
347
+ await (0, saml_helpers_1.setSamlLoginEnabled)(prefs.loginEnabled ?? (0, sso_helpers_1.isSamlLoginEnabled)());
348
+ (0, saml_helpers_1.setSamlLoginLabel)(prefs.loginLabel ?? (0, sso_helpers_1.getSamlLoginLabel)());
349
+ }
350
+ async loadFromDbAndApplySamlPreferences(apply = true, broadcastReload = true) {
351
+ const samlPreferences = await this.settingsRepository.findOne({
352
+ where: { key: constants_1.SAML_PREFERENCES_DB_KEY },
353
+ });
354
+ if (samlPreferences) {
355
+ const prefs = (0, n8n_workflow_1.jsonParse)(samlPreferences.value);
356
+ if (prefs) {
357
+ if (apply) {
358
+ await this.setSamlPreferences(prefs, true, broadcastReload);
359
+ }
360
+ else {
361
+ await this.loadPreferencesWithoutValidation(prefs);
362
+ }
363
+ return prefs;
364
+ }
365
+ }
366
+ return;
367
+ }
368
+ async saveSamlPreferencesToDb() {
369
+ const samlPreferences = await this.settingsRepository.findOne({
370
+ where: { key: constants_1.SAML_PREFERENCES_DB_KEY },
371
+ });
372
+ const settingsValue = JSON.stringify(this.samlPreferences);
373
+ let result;
374
+ if (samlPreferences) {
375
+ samlPreferences.value = settingsValue;
376
+ result = await this.settingsRepository.save(samlPreferences, {
377
+ transaction: false,
378
+ });
379
+ }
380
+ else {
381
+ result = await this.settingsRepository.save({
382
+ key: constants_1.SAML_PREFERENCES_DB_KEY,
383
+ value: settingsValue,
384
+ loadOnStartup: true,
385
+ }, { transaction: false });
386
+ }
387
+ if (result)
388
+ return (0, n8n_workflow_1.jsonParse)(result.value);
389
+ return;
390
+ }
391
+ async fetchMetadataFromUrl() {
392
+ await this.loadSamlify();
393
+ if (!this._samlPreferences.metadataUrl)
394
+ throw new bad_request_error_1.BadRequestError('Error fetching SAML Metadata, no Metadata URL set');
395
+ try {
396
+ const httpsAgent = (0, n8n_core_1.createHttpsProxyAgent)(null, this._samlPreferences.metadataUrl, {
397
+ rejectUnauthorized: !this._samlPreferences.ignoreSSL,
398
+ });
399
+ const httpAgent = (0, n8n_core_1.createHttpProxyAgent)(null, this._samlPreferences.metadataUrl);
400
+ const response = await axios_1.default.get(this._samlPreferences.metadataUrl, {
401
+ httpsAgent,
402
+ httpAgent,
403
+ });
404
+ if (response.status === 200 && response.data) {
405
+ const xml = (await response.data);
406
+ const validationResult = await this.validator.validateMetadata(xml);
407
+ if (!validationResult) {
408
+ throw new bad_request_error_1.BadRequestError(`Data received from ${this._samlPreferences.metadataUrl} is not valid SAML metadata.`);
409
+ }
410
+ return xml;
411
+ }
412
+ }
413
+ catch (error) {
414
+ throw new bad_request_error_1.BadRequestError(`Error fetching SAML Metadata from ${this._samlPreferences.metadataUrl}: ${error}`);
415
+ }
416
+ return;
417
+ }
418
+ async getAttributesFromLoginResponse(req, binding) {
419
+ let parsedSamlResponse;
420
+ if (!this._samlPreferences.mapping)
421
+ throw new bad_request_error_1.BadRequestError('Error fetching SAML Attributes, no Attribute mapping set');
422
+ try {
423
+ await this.loadSamlify();
424
+ parsedSamlResponse = await this.getServiceProviderInstance().parseLoginResponse(this.getIdentityProviderInstance(), binding, req);
425
+ }
426
+ catch (error) {
427
+ throw new auth_error_1.AuthError(`SAML Authentication failed. Could not parse SAML response. ${error instanceof Error ? error.message : error}`);
428
+ }
429
+ const { attributes, missingAttributes } = (0, saml_helpers_1.getMappedSamlAttributesFromFlowResult)(parsedSamlResponse, this._samlPreferences.mapping, {
430
+ instanceRole: await this.provisioningService.getInstanceRoleClaimName(),
431
+ projectRoles: await this.provisioningService.getProjectsRolesClaimName(),
432
+ });
433
+ if (!attributes) {
434
+ throw new auth_error_1.AuthError('SAML Authentication failed. Invalid SAML response.');
435
+ }
436
+ if (missingAttributes.length > 0) {
437
+ throw new auth_error_1.AuthError(`SAML Authentication failed. Invalid SAML response (missing attributes: ${missingAttributes.join(', ')}).`);
438
+ }
439
+ return attributes;
440
+ }
441
+ async reset() {
442
+ await (0, saml_helpers_1.setSamlLoginEnabled)(false);
443
+ await this.settingsRepository.delete({ key: constants_1.SAML_PREFERENCES_DB_KEY });
444
+ }
445
+ };
446
+ exports.SamlService = SamlService;
447
+ __decorate([
448
+ (0, decorators_1.OnPubSubEvent)('reload-saml-config'),
449
+ __metadata("design:type", Function),
450
+ __metadata("design:paramtypes", []),
451
+ __metadata("design:returntype", Promise)
452
+ ], SamlService.prototype, "reload", null);
453
+ exports.SamlService = SamlService = __decorate([
454
+ (0, di_1.Service)(),
455
+ __metadata("design:paramtypes", [backend_common_1.Logger,
456
+ url_service_1.UrlService,
457
+ saml_validator_1.SamlValidator,
458
+ db_1.UserRepository,
459
+ db_1.SettingsRepository,
460
+ n8n_core_1.InstanceSettings,
461
+ provisioning_service_ee_1.ProvisioningService])
462
+ ], SamlService);
@@ -0,0 +1,2 @@
1
+ import type { XMLFileInfo } from 'xmllint-wasm';
2
+ export declare const xmlFileInfo: XMLFileInfo;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.xmlFileInfo = void 0;
4
+ exports.xmlFileInfo = {
5
+ fileName: 'MetadataExchange.xsd',
6
+ contents: `<?xml version='1.0' encoding='UTF-8' ?>
7
+ <!--
8
+ (c) 2004-2006 BEA Systems Inc., Computer Associates International, Inc.,
9
+ International Business Machines Corporation, Microsoft Corporation,
10
+ Inc., SAP AG, Sun Microsystems, and webMethods. All rights reserved.
11
+
12
+ Permission to copy and display the WS-MetadataExchange Specification
13
+ (the "Specification"), in any medium without fee or royalty is hereby
14
+ granted, provided that you include the following on ALL copies of the
15
+ Specification that you make:
16
+
17
+ 1. A link or URL to the Specification at this location.
18
+ 2. The copyright notice as shown in the Specification.
19
+
20
+ BEA Systems, Computer Associates, IBM, Microsoft, SAP, Sun, and
21
+ webMethods (collectively, the "Authors") each agree to grant you a
22
+ license, under royalty-free and otherwise reasonable,
23
+ non-discriminatory terms and conditions, to their respective essential
24
+ patent claims that they deem necessary to implement the
25
+ WS-MetadataExchange Specification.
26
+
27
+ THE SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO
28
+ REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
29
+ LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
30
+ PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE
31
+ SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
32
+ IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY
33
+ PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
34
+
35
+ THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
36
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY
37
+ USE OR DISTRIBUTION OF THE SPECIFICATIONS.
38
+
39
+ The name and trademarks of the Authors may NOT be used in any manner,
40
+ including advertising or publicity pertaining to the Specifications or
41
+ their contents without specific, written prior permission. Title to
42
+ copyright in the Specifications will at all times remain with the
43
+ Authors.
44
+
45
+ No other rights are granted by implication, estoppel or otherwise.
46
+ -->
47
+
48
+ <xs:schema
49
+ targetNamespace='http://schemas.xmlsoap.org/ws/2004/09/mex'
50
+ xmlns:tns='http://schemas.xmlsoap.org/ws/2004/09/mex'
51
+ xmlns:wsa10='http://www.w3.org/2005/08/addressing'
52
+ xmlns:wsa04='http://schemas.xmlsoap.org/ws/2004/08/addressing'
53
+ xmlns:xs='http://www.w3.org/2001/XMLSchema'
54
+ elementFormDefault='qualified'
55
+ blockDefault='#all' >
56
+
57
+ <!-- Get Metadata request -->
58
+ <xs:element name='GetMetadata' >
59
+ <xs:complexType>
60
+ <xs:sequence>
61
+ <xs:element ref='tns:Dialect' minOccurs='0' />
62
+ <xs:element ref='tns:Identifier' minOccurs='0' />
63
+ </xs:sequence>
64
+ <xs:anyAttribute namespace='##other' processContents='lax' />
65
+ </xs:complexType>
66
+ </xs:element>
67
+
68
+ <xs:element name='Dialect' type='xs:anyURI' />
69
+ <xs:element name='Identifier' type='xs:anyURI' />
70
+
71
+ <!-- Get Metadata response -->
72
+ <xs:element name='Metadata' >
73
+ <xs:complexType>
74
+ <xs:sequence>
75
+ <xs:element ref='tns:MetadataSection'
76
+ minOccurs='0'
77
+ maxOccurs='unbounded' />
78
+ <xs:any namespace='##other' processContents='lax'
79
+ minOccurs='0'
80
+ maxOccurs='unbounded' />
81
+ </xs:sequence>
82
+ <xs:anyAttribute namespace='##other' processContents='lax' />
83
+ </xs:complexType>
84
+ </xs:element>
85
+
86
+ <xs:element name='MetadataSection' >
87
+ <xs:complexType>
88
+ <xs:choice>
89
+ <xs:any namespace='##other' processContents='lax' />
90
+ <xs:element ref='tns:MetadataReference' />
91
+ <xs:element ref='tns:Location' />
92
+ </xs:choice>
93
+ <xs:attribute name='Dialect' type='xs:anyURI' use='required' />
94
+ <xs:attribute name='Identifier' type='xs:anyURI' />
95
+ <xs:anyAttribute namespace='##other' processContents='lax' />
96
+ </xs:complexType>
97
+ </xs:element>
98
+
99
+ <!--
100
+ Ideally, the type of the MetadataReference would have been
101
+ the union of wsa04:EndpointReferenceType and
102
+ wsa10:EndpointReferenceType but unfortunately xs:union only
103
+ works for simple types. As a result, we have to define
104
+ the mex:MetadataReference using xs:any.
105
+ -->
106
+
107
+ <xs:element name='MetadataReference'>
108
+ <xs:complexType>
109
+ <xs:sequence>
110
+ <xs:any minOccurs='1' maxOccurs='unbounded'
111
+ processContents='lax' namespace='##other' />
112
+ </xs:sequence>
113
+ </xs:complexType>
114
+ </xs:element>
115
+ <xs:element name='Location'
116
+ type='xs:anyURI' />
117
+ </xs:schema>`,
118
+ };
@@ -0,0 +1,2 @@
1
+ import type { XMLFileInfo } from 'xmllint-wasm';
2
+ export declare const xmlFileInfo: XMLFileInfo;