@friggframework/core 2.0.0-next.10 → 2.0.0-next.101

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 (344) hide show
  1. package/CLAUDE.md +702 -0
  2. package/README.md +959 -50
  3. package/admin-scripts/index.js +52 -0
  4. package/admin-scripts/repositories/admin-script-execution-repository-documentdb.js +21 -0
  5. package/admin-scripts/repositories/admin-script-execution-repository-factory.js +51 -0
  6. package/admin-scripts/repositories/admin-script-execution-repository-interface.js +166 -0
  7. package/admin-scripts/repositories/admin-script-execution-repository-mongo.js +228 -0
  8. package/admin-scripts/repositories/admin-script-execution-repository-postgres.js +268 -0
  9. package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
  10. package/admin-scripts/repositories/script-schedule-repository-factory.js +51 -0
  11. package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
  12. package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
  13. package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
  14. package/application/commands/README.md +451 -0
  15. package/application/commands/admin-script-commands.js +358 -0
  16. package/application/commands/credential-commands.js +245 -0
  17. package/application/commands/entity-commands.js +336 -0
  18. package/application/commands/integration-commands.js +343 -0
  19. package/application/commands/process-commands.js +135 -0
  20. package/application/commands/scheduler-commands.js +263 -0
  21. package/application/commands/user-commands.js +312 -0
  22. package/application/index.js +82 -0
  23. package/assertions/index.js +0 -3
  24. package/core/CLAUDE.md +690 -0
  25. package/core/Worker.js +60 -24
  26. package/core/create-handler.js +84 -6
  27. package/credential/repositories/credential-repository-documentdb.js +304 -0
  28. package/credential/repositories/credential-repository-factory.js +54 -0
  29. package/credential/repositories/credential-repository-interface.js +98 -0
  30. package/credential/repositories/credential-repository-mongo.js +269 -0
  31. package/credential/repositories/credential-repository-postgres.js +287 -0
  32. package/credential/repositories/credential-repository.js +300 -0
  33. package/credential/use-cases/get-credential-for-user.js +25 -0
  34. package/credential/use-cases/update-authentication-status.js +15 -0
  35. package/database/MONGODB_TRANSACTION_FIX.md +198 -0
  36. package/database/adapters/lambda-invoker.js +97 -0
  37. package/database/config.js +154 -0
  38. package/database/documentdb-encryption-service.js +330 -0
  39. package/database/documentdb-utils.js +136 -0
  40. package/database/encryption/README.md +839 -0
  41. package/database/encryption/documentdb-encryption-service.md +3575 -0
  42. package/database/encryption/encryption-schema-registry.js +401 -0
  43. package/database/encryption/field-encryption-service.js +254 -0
  44. package/database/encryption/logger.js +79 -0
  45. package/database/encryption/prisma-encryption-extension.js +230 -0
  46. package/database/index.js +21 -21
  47. package/database/prisma.js +182 -0
  48. package/database/repositories/health-check-repository-documentdb.js +138 -0
  49. package/database/repositories/health-check-repository-factory.js +48 -0
  50. package/database/repositories/health-check-repository-interface.js +82 -0
  51. package/database/repositories/health-check-repository-mongodb.js +89 -0
  52. package/database/repositories/health-check-repository-postgres.js +82 -0
  53. package/database/repositories/migration-status-repository-s3.js +137 -0
  54. package/database/use-cases/check-database-health-use-case.js +29 -0
  55. package/database/use-cases/check-database-state-use-case.js +81 -0
  56. package/database/use-cases/check-encryption-health-use-case.js +83 -0
  57. package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
  58. package/database/use-cases/get-migration-status-use-case.js +93 -0
  59. package/database/use-cases/run-database-migration-use-case.js +139 -0
  60. package/database/use-cases/test-encryption-use-case.js +253 -0
  61. package/database/use-cases/trigger-database-migration-use-case.js +157 -0
  62. package/database/utils/mongodb-collection-utils.js +94 -0
  63. package/database/utils/mongodb-schema-init.js +108 -0
  64. package/database/utils/prisma-runner.js +477 -0
  65. package/database/utils/prisma-schema-parser.js +182 -0
  66. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
  67. package/encrypt/Cryptor.js +34 -168
  68. package/encrypt/index.js +1 -2
  69. package/errors/client-safe-error.js +26 -0
  70. package/errors/fetch-error.js +15 -7
  71. package/errors/index.js +2 -0
  72. package/generated/prisma-mongodb/client.d.ts +1 -0
  73. package/generated/prisma-mongodb/client.js +5 -0
  74. package/generated/prisma-mongodb/default.d.ts +1 -0
  75. package/generated/prisma-mongodb/default.js +5 -0
  76. package/generated/prisma-mongodb/edge.d.ts +1 -0
  77. package/generated/prisma-mongodb/edge.js +374 -0
  78. package/generated/prisma-mongodb/index-browser.js +356 -0
  79. package/generated/prisma-mongodb/index.d.ts +25667 -0
  80. package/generated/prisma-mongodb/index.js +399 -0
  81. package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  82. package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  83. package/generated/prisma-mongodb/package.json +183 -0
  84. package/generated/prisma-mongodb/runtime/edge-esm.js +35 -0
  85. package/generated/prisma-mongodb/runtime/edge.js +35 -0
  86. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  87. package/generated/prisma-mongodb/runtime/index-browser.js +17 -0
  88. package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
  89. package/generated/prisma-mongodb/runtime/library.js +147 -0
  90. package/generated/prisma-mongodb/runtime/react-native.js +84 -0
  91. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +85 -0
  92. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +38 -0
  93. package/generated/prisma-mongodb/schema.prisma +432 -0
  94. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +5 -0
  95. package/generated/prisma-mongodb/wasm-worker-loader.mjs +5 -0
  96. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  97. package/generated/prisma-mongodb/wasm.js +381 -0
  98. package/generated/prisma-postgresql/client.d.ts +1 -0
  99. package/generated/prisma-postgresql/client.js +5 -0
  100. package/generated/prisma-postgresql/default.d.ts +1 -0
  101. package/generated/prisma-postgresql/default.js +5 -0
  102. package/generated/prisma-postgresql/edge.d.ts +1 -0
  103. package/generated/prisma-postgresql/edge.js +395 -0
  104. package/generated/prisma-postgresql/index-browser.js +377 -0
  105. package/generated/prisma-postgresql/index.d.ts +28455 -0
  106. package/generated/prisma-postgresql/index.js +420 -0
  107. package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  108. package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  109. package/generated/prisma-postgresql/package.json +183 -0
  110. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  111. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  112. package/generated/prisma-postgresql/runtime/edge-esm.js +35 -0
  113. package/generated/prisma-postgresql/runtime/edge.js +35 -0
  114. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  115. package/generated/prisma-postgresql/runtime/index-browser.js +17 -0
  116. package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
  117. package/generated/prisma-postgresql/runtime/library.js +147 -0
  118. package/generated/prisma-postgresql/runtime/react-native.js +84 -0
  119. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +85 -0
  120. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +38 -0
  121. package/generated/prisma-postgresql/schema.prisma +414 -0
  122. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +5 -0
  123. package/generated/prisma-postgresql/wasm-worker-loader.mjs +5 -0
  124. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  125. package/generated/prisma-postgresql/wasm.js +402 -0
  126. package/handlers/WEBHOOKS.md +653 -0
  127. package/handlers/app-definition-loader.js +43 -0
  128. package/handlers/app-handler-helpers.js +3 -3
  129. package/handlers/backend-utils.js +271 -42
  130. package/handlers/database-migration-handler.js +227 -0
  131. package/handlers/integration-event-dispatcher.js +54 -0
  132. package/handlers/middleware/admin-auth.js +73 -0
  133. package/handlers/routers/HEALTHCHECK.md +342 -0
  134. package/handlers/routers/auth.js +4 -15
  135. package/handlers/routers/db-migration.handler.js +29 -0
  136. package/handlers/routers/db-migration.js +311 -0
  137. package/handlers/routers/health.js +518 -0
  138. package/handlers/routers/integration-defined-routers.js +85 -10
  139. package/handlers/routers/integration-webhook-routers.js +67 -0
  140. package/handlers/routers/reporting.js +9 -0
  141. package/handlers/routers/user.js +27 -5
  142. package/handlers/routers/websocket.js +5 -3
  143. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  144. package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
  145. package/handlers/workers/db-migration.js +352 -0
  146. package/handlers/workers/dlq-processor.js +63 -0
  147. package/handlers/workers/integration-defined-workers.js +13 -7
  148. package/index.js +91 -46
  149. package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +184 -0
  150. package/infrastructure/scheduler/index.js +33 -0
  151. package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
  152. package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
  153. package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
  154. package/integrations/EXTENSIONS.md +240 -0
  155. package/integrations/WEBHOOK-QUICKSTART.md +151 -0
  156. package/integrations/extension.js +254 -0
  157. package/integrations/index.js +20 -10
  158. package/integrations/integration-base.js +633 -72
  159. package/integrations/integration-router.js +398 -180
  160. package/integrations/options.js +1 -1
  161. package/integrations/repositories/config-patch-shared.js +43 -0
  162. package/integrations/repositories/integration-mapping-repository-documentdb.js +280 -0
  163. package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
  164. package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
  165. package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
  166. package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
  167. package/integrations/repositories/integration-mapping-repository.js +156 -0
  168. package/integrations/repositories/integration-repository-documentdb.js +284 -0
  169. package/integrations/repositories/integration-repository-factory.js +51 -0
  170. package/integrations/repositories/integration-repository-interface.js +173 -0
  171. package/integrations/repositories/integration-repository-mongo.js +414 -0
  172. package/integrations/repositories/integration-repository-postgres.js +452 -0
  173. package/integrations/repositories/process-repository-documentdb.js +311 -0
  174. package/integrations/repositories/process-repository-factory.js +53 -0
  175. package/integrations/repositories/process-repository-interface.js +136 -0
  176. package/integrations/repositories/process-repository-mongo.js +262 -0
  177. package/integrations/repositories/process-repository-postgres.js +380 -0
  178. package/integrations/repositories/process-update-ops-shared.js +112 -0
  179. package/integrations/tests/doubles/config-capturing-integration.js +81 -0
  180. package/integrations/tests/doubles/dummy-integration-class.js +113 -0
  181. package/integrations/tests/doubles/test-integration-repository.js +146 -0
  182. package/integrations/use-cases/create-integration.js +215 -0
  183. package/integrations/use-cases/create-process.js +130 -0
  184. package/integrations/use-cases/delete-integration-for-user.js +119 -0
  185. package/integrations/use-cases/find-integration-by-entity-external-id.js +74 -0
  186. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +76 -0
  187. package/integrations/use-cases/get-integration-for-user.js +78 -0
  188. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  189. package/integrations/use-cases/get-integration-instance.js +83 -0
  190. package/integrations/use-cases/get-integrations-for-user.js +88 -0
  191. package/integrations/use-cases/get-possible-integrations.js +27 -0
  192. package/integrations/use-cases/get-process.js +89 -0
  193. package/integrations/use-cases/index.js +19 -0
  194. package/integrations/use-cases/list-integrations-by-entity-external-id.js +46 -0
  195. package/integrations/use-cases/load-integration-context.js +71 -0
  196. package/integrations/use-cases/patch-integration-config.js +39 -0
  197. package/integrations/use-cases/process-errors.js +28 -0
  198. package/integrations/use-cases/update-integration-config.js +32 -0
  199. package/integrations/use-cases/update-integration-messages.js +44 -0
  200. package/integrations/use-cases/update-integration-status.js +32 -0
  201. package/integrations/use-cases/update-integration.js +92 -0
  202. package/integrations/use-cases/update-process-metrics.js +216 -0
  203. package/integrations/use-cases/update-process-state.js +163 -0
  204. package/integrations/utils/map-integration-dto.js +37 -0
  205. package/jest-global-setup-noop.js +3 -0
  206. package/jest-global-teardown-noop.js +3 -0
  207. package/logs/logger.js +0 -4
  208. package/{module-plugin → modules}/index.js +0 -10
  209. package/modules/module-factory.js +56 -0
  210. package/modules/module.js +287 -0
  211. package/modules/repositories/module-repository-documentdb.js +350 -0
  212. package/modules/repositories/module-repository-factory.js +40 -0
  213. package/modules/repositories/module-repository-interface.js +145 -0
  214. package/modules/repositories/module-repository-mongo.js +436 -0
  215. package/modules/repositories/module-repository-postgres.js +481 -0
  216. package/modules/repositories/module-repository.js +369 -0
  217. package/modules/requester/api-key.js +52 -0
  218. package/modules/requester/oauth-2.js +396 -0
  219. package/modules/requester/requester.js +334 -0
  220. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  221. package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
  222. package/modules/tests/doubles/test-module-factory.js +16 -0
  223. package/modules/tests/doubles/test-module-repository.js +39 -0
  224. package/modules/use-cases/get-entities-for-user.js +32 -0
  225. package/modules/use-cases/get-entity-options-by-id.js +71 -0
  226. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  227. package/modules/use-cases/get-module-instance-from-type.js +34 -0
  228. package/modules/use-cases/get-module.js +74 -0
  229. package/modules/use-cases/process-authorization-callback.js +243 -0
  230. package/modules/use-cases/refresh-entity-options.js +72 -0
  231. package/modules/use-cases/test-module-auth.js +72 -0
  232. package/modules/utils/map-module-dto.js +18 -0
  233. package/package.json +82 -50
  234. package/prisma-mongodb/schema.prisma +432 -0
  235. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  236. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  237. package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
  238. package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
  239. package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
  240. package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
  241. package/prisma-postgresql/migrations/20260625000000_add_user_organization_id_index/migration.sql +2 -0
  242. package/prisma-postgresql/migrations/20260703000000_add_integration_status_in_creation_in_deletion/migration.sql +11 -0
  243. package/prisma-postgresql/migrations/20260703000001_integration_status_default_in_creation/migration.sql +8 -0
  244. package/prisma-postgresql/migrations/20260706000000_add_admin_script_execution_and_schedule/migration.sql +61 -0
  245. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  246. package/prisma-postgresql/schema.prisma +414 -0
  247. package/queues/queuer-util.js +103 -21
  248. package/reporting/README.md +86 -0
  249. package/reporting/index.js +17 -0
  250. package/reporting/reporting-router.js +77 -0
  251. package/reporting/repositories/reporting-repository-documentdb.js +127 -0
  252. package/reporting/repositories/reporting-repository-factory.js +35 -0
  253. package/reporting/repositories/reporting-repository-interface.js +16 -0
  254. package/reporting/repositories/reporting-repository-mongo.js +54 -0
  255. package/reporting/repositories/reporting-repository-postgres.js +70 -0
  256. package/reporting/use-cases/index.js +6 -0
  257. package/reporting/use-cases/list-integrations-report.js +142 -0
  258. package/syncs/manager.js +468 -443
  259. package/syncs/repositories/sync-repository-documentdb.js +240 -0
  260. package/syncs/repositories/sync-repository-factory.js +43 -0
  261. package/syncs/repositories/sync-repository-interface.js +109 -0
  262. package/syncs/repositories/sync-repository-mongo.js +239 -0
  263. package/syncs/repositories/sync-repository-postgres.js +319 -0
  264. package/syncs/sync.js +0 -1
  265. package/token/repositories/token-repository-documentdb.js +137 -0
  266. package/token/repositories/token-repository-factory.js +40 -0
  267. package/token/repositories/token-repository-interface.js +131 -0
  268. package/token/repositories/token-repository-mongo.js +219 -0
  269. package/token/repositories/token-repository-postgres.js +264 -0
  270. package/token/repositories/token-repository.js +219 -0
  271. package/types/associations/index.d.ts +0 -17
  272. package/types/core/index.d.ts +12 -4
  273. package/types/database/index.d.ts +10 -2
  274. package/types/encrypt/index.d.ts +5 -3
  275. package/types/integrations/index.d.ts +3 -8
  276. package/types/module-plugin/index.d.ts +17 -69
  277. package/types/syncs/index.d.ts +0 -17
  278. package/user/repositories/user-repository-documentdb.js +458 -0
  279. package/user/repositories/user-repository-factory.js +52 -0
  280. package/user/repositories/user-repository-interface.js +214 -0
  281. package/user/repositories/user-repository-mongo.js +323 -0
  282. package/user/repositories/user-repository-postgres.js +377 -0
  283. package/user/tests/doubles/test-user-repository.js +72 -0
  284. package/user/use-cases/authenticate-user.js +127 -0
  285. package/user/use-cases/authenticate-with-shared-secret.js +48 -0
  286. package/user/use-cases/create-individual-user.js +61 -0
  287. package/user/use-cases/create-organization-user.js +47 -0
  288. package/user/use-cases/create-token-for-user-id.js +30 -0
  289. package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
  290. package/user/use-cases/get-user-from-bearer-token.js +77 -0
  291. package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
  292. package/user/use-cases/login-user.js +122 -0
  293. package/user/user.js +125 -0
  294. package/utils/backend-path.js +38 -0
  295. package/utils/index.js +6 -0
  296. package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
  297. package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
  298. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  299. package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
  300. package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
  301. package/websocket/repositories/websocket-connection-repository.js +161 -0
  302. package/assertions/is-equal.js +0 -17
  303. package/associations/model.js +0 -54
  304. package/database/models/IndividualUser.js +0 -76
  305. package/database/models/OrganizationUser.js +0 -29
  306. package/database/models/State.js +0 -9
  307. package/database/models/Token.js +0 -70
  308. package/database/models/UserModel.js +0 -7
  309. package/database/models/WebsocketConnection.js +0 -49
  310. package/database/mongo.js +0 -45
  311. package/database/mongoose.js +0 -5
  312. package/encrypt/Cryptor.test.js +0 -32
  313. package/encrypt/encrypt.js +0 -132
  314. package/encrypt/encrypt.test.js +0 -1069
  315. package/encrypt/test-encrypt.js +0 -107
  316. package/errors/base-error.test.js +0 -32
  317. package/errors/fetch-error.test.js +0 -79
  318. package/errors/halt-error.test.js +0 -11
  319. package/errors/validation-errors.test.js +0 -120
  320. package/handlers/routers/middleware/loadUser.js +0 -15
  321. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  322. package/integrations/create-frigg-backend.js +0 -31
  323. package/integrations/integration-factory.js +0 -251
  324. package/integrations/integration-mapping.js +0 -43
  325. package/integrations/integration-model.js +0 -46
  326. package/integrations/integration-user.js +0 -144
  327. package/integrations/test/integration-base.test.js +0 -144
  328. package/lambda/TimeoutCatcher.test.js +0 -68
  329. package/logs/logger.test.js +0 -76
  330. package/module-plugin/auther.js +0 -393
  331. package/module-plugin/credential.js +0 -22
  332. package/module-plugin/entity-manager.js +0 -70
  333. package/module-plugin/entity.js +0 -46
  334. package/module-plugin/manager.js +0 -169
  335. package/module-plugin/module-factory.js +0 -61
  336. package/module-plugin/requester/api-key.js +0 -36
  337. package/module-plugin/requester/oauth-2.js +0 -219
  338. package/module-plugin/requester/requester.js +0 -165
  339. package/module-plugin/requester/requester.test.js +0 -28
  340. package/module-plugin/test/auther.test.js +0 -97
  341. package/syncs/model.js +0 -62
  342. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  343. /package/{module-plugin → modules}/requester/basic.js +0 -0
  344. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
@@ -2,23 +2,220 @@ const express = require('express');
2
2
  const { get } = require('../assertions');
3
3
  const Boom = require('@hapi/boom');
4
4
  const catchAsyncError = require('express-async-handler');
5
- const { debug } = require('../logs');
6
- function createIntegrationRouter(params) {
7
- const router = get(params, 'router', express());
8
- const factory = get(params, 'factory');
9
- const getUserId = get(params, 'getUserId', (req) => null);
10
- const requireLoggedInUser = get(
11
- params,
12
- 'requireLoggedInUser',
13
- (req, res, next) => next()
14
- );
15
-
16
- router.all('/api/entities*', requireLoggedInUser);
17
- router.all('/api/authorize', requireLoggedInUser);
18
- router.all('/api/integrations*', requireLoggedInUser);
19
-
20
- setIntegrationRoutes(router, factory, getUserId);
21
- setEntityRoutes(router, factory, getUserId);
5
+ const {
6
+ createIntegrationRepository,
7
+ } = require('./repositories/integration-repository-factory');
8
+ const {
9
+ DeleteIntegrationForUser,
10
+ } = require('./use-cases/delete-integration-for-user');
11
+ const {
12
+ GetIntegrationsForUser,
13
+ } = require('./use-cases/get-integrations-for-user');
14
+ const {
15
+ createCredentialRepository,
16
+ } = require('../credential/repositories/credential-repository-factory');
17
+ const {
18
+ GetCredentialForUser,
19
+ } = require('../credential/use-cases/get-credential-for-user');
20
+ const { CreateIntegration } = require('./use-cases/create-integration');
21
+ const { ModuleFactory } = require('../modules/module-factory');
22
+ const {
23
+ createModuleRepository,
24
+ } = require('../modules/repositories/module-repository-factory');
25
+ const {
26
+ GetEntitiesForUser,
27
+ } = require('../modules/use-cases/get-entities-for-user');
28
+ const { loadAppDefinition } = require('../handlers/app-definition-loader');
29
+ const {
30
+ GetIntegrationInstance,
31
+ } = require('./use-cases/get-integration-instance');
32
+ const { UpdateIntegration } = require('./use-cases/update-integration');
33
+ const {
34
+ getModulesDefinitionFromIntegrationClasses,
35
+ } = require('./utils/map-integration-dto');
36
+ const {
37
+ GetModuleInstanceFromType,
38
+ } = require('../modules/use-cases/get-module-instance-from-type');
39
+ const {
40
+ GetEntityOptionsByType,
41
+ } = require('../modules/use-cases/get-entity-options-by-type');
42
+ const { TestModuleAuth } = require('../modules/use-cases/test-module-auth');
43
+ const { GetModule } = require('../modules/use-cases/get-module');
44
+ const {
45
+ GetEntityOptionsById,
46
+ } = require('../modules/use-cases/get-entity-options-by-id');
47
+ const {
48
+ RefreshEntityOptions,
49
+ } = require('../modules/use-cases/refresh-entity-options');
50
+ const {
51
+ GetPossibleIntegrations,
52
+ } = require('./use-cases/get-possible-integrations');
53
+ const {
54
+ createUserRepository,
55
+ } = require('../user/repositories/user-repository-factory');
56
+ const {
57
+ GetUserFromBearerToken,
58
+ } = require('../user/use-cases/get-user-from-bearer-token');
59
+ const {
60
+ GetUserFromXFriggHeaders,
61
+ } = require('../user/use-cases/get-user-from-x-frigg-headers');
62
+ const {
63
+ GetUserFromAdopterJwt,
64
+ } = require('../user/use-cases/get-user-from-adopter-jwt');
65
+ const {
66
+ AuthenticateWithSharedSecret,
67
+ } = require('../user/use-cases/authenticate-with-shared-secret');
68
+ const { AuthenticateUser } = require('../user/use-cases/authenticate-user');
69
+ const {
70
+ ProcessAuthorizationCallback,
71
+ } = require('../modules/use-cases/process-authorization-callback');
72
+
73
+ function createIntegrationRouter() {
74
+ const { integrations: integrationClasses, userConfig } =
75
+ loadAppDefinition();
76
+ const moduleRepository = createModuleRepository();
77
+ const integrationRepository = createIntegrationRepository();
78
+ const credentialRepository = createCredentialRepository();
79
+ const userRepository = createUserRepository();
80
+
81
+ const getUserFromBearerToken = new GetUserFromBearerToken({
82
+ userRepository,
83
+ userConfig,
84
+ });
85
+
86
+ const getUserFromXFriggHeaders = new GetUserFromXFriggHeaders({
87
+ userRepository,
88
+ userConfig,
89
+ });
90
+
91
+ const getUserFromAdopterJwt = new GetUserFromAdopterJwt({
92
+ userRepository,
93
+ userConfig,
94
+ });
95
+
96
+ const authenticateWithSharedSecret = new AuthenticateWithSharedSecret();
97
+
98
+ const authenticateUser = new AuthenticateUser({
99
+ getUserFromBearerToken,
100
+ getUserFromXFriggHeaders,
101
+ getUserFromAdopterJwt,
102
+ authenticateWithSharedSecret,
103
+ userConfig,
104
+ });
105
+
106
+ const moduleFactory = new ModuleFactory({
107
+ moduleRepository,
108
+ moduleDefinitions:
109
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
110
+ });
111
+ const deleteIntegrationForUser = new DeleteIntegrationForUser({
112
+ integrationRepository,
113
+ integrationClasses,
114
+ moduleFactory,
115
+ });
116
+
117
+ const getIntegrationsForUser = new GetIntegrationsForUser({
118
+ integrationRepository,
119
+ integrationClasses,
120
+ moduleFactory,
121
+ moduleRepository,
122
+ });
123
+
124
+ const getCredentialForUser = new GetCredentialForUser({
125
+ credentialRepository,
126
+ });
127
+
128
+ const createIntegration = new CreateIntegration({
129
+ integrationRepository,
130
+ integrationClasses,
131
+ moduleFactory,
132
+ });
133
+
134
+ const getEntitiesForUser = new GetEntitiesForUser({
135
+ moduleRepository,
136
+ moduleDefinitions:
137
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
138
+ });
139
+
140
+ const getIntegrationInstance = new GetIntegrationInstance({
141
+ integrationRepository,
142
+ integrationClasses,
143
+ moduleFactory,
144
+ });
145
+
146
+ const updateIntegration = new UpdateIntegration({
147
+ integrationRepository,
148
+ integrationClasses,
149
+ moduleFactory,
150
+ });
151
+
152
+ const getModuleInstanceFromType = new GetModuleInstanceFromType({
153
+ moduleDefinitions:
154
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
155
+ });
156
+
157
+ const getEntityOptionsByType = new GetEntityOptionsByType({
158
+ moduleDefinitions:
159
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
160
+ });
161
+
162
+ const testModuleAuth = new TestModuleAuth({
163
+ moduleRepository,
164
+ moduleDefinitions:
165
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
166
+ });
167
+
168
+ const getModule = new GetModule({
169
+ moduleRepository,
170
+ moduleDefinitions:
171
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
172
+ });
173
+
174
+ const getEntityOptionsById = new GetEntityOptionsById({
175
+ moduleRepository,
176
+ moduleDefinitions:
177
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
178
+ });
179
+
180
+ const refreshEntityOptions = new RefreshEntityOptions({
181
+ moduleRepository,
182
+ moduleDefinitions:
183
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
184
+ });
185
+
186
+ const getPossibleIntegrations = new GetPossibleIntegrations({
187
+ integrationClasses,
188
+ });
189
+
190
+ const processAuthorizationCallback = new ProcessAuthorizationCallback({
191
+ moduleRepository,
192
+ credentialRepository,
193
+ integrationRepository,
194
+ moduleDefinitions:
195
+ getModulesDefinitionFromIntegrationClasses(integrationClasses),
196
+ });
197
+
198
+ const router = express();
199
+
200
+ setIntegrationRoutes(router, authenticateUser, {
201
+ createIntegration,
202
+ deleteIntegrationForUser,
203
+ getIntegrationsForUser,
204
+ getEntitiesForUser,
205
+ getIntegrationInstance,
206
+ updateIntegration,
207
+ getPossibleIntegrations,
208
+ });
209
+ setEntityRoutes(router, authenticateUser, {
210
+ getCredentialForUser,
211
+ getModuleInstanceFromType,
212
+ getEntityOptionsByType,
213
+ testModuleAuth,
214
+ getModule,
215
+ getEntityOptionsById,
216
+ refreshEntityOptions,
217
+ processAuthorizationCallback,
218
+ });
22
219
  return router;
23
220
  }
24
221
 
@@ -46,111 +243,95 @@ function checkRequiredParams(params, requiredKeys) {
46
243
  return returnDict;
47
244
  }
48
245
 
49
- function setIntegrationRoutes(router, factory, getUserId) {
50
- const { moduleFactory, integrationFactory, IntegrationHelper } = factory;
246
+ /**
247
+ * Sets up integration-related routes on the provided Express router
248
+ * @param {express.Router} router - Express router instance to add routes to
249
+ * @param {import('../user/use-cases/authenticate-user').AuthenticateUser} authenticateUser - Use case for multi-mode user authentication
250
+ * @param {Object} useCases - use cases for integration management
251
+ */
252
+ function setIntegrationRoutes(router, authenticateUser, useCases) {
253
+ const {
254
+ createIntegration,
255
+ deleteIntegrationForUser,
256
+ getIntegrationsForUser,
257
+ getEntitiesForUser,
258
+ getIntegrationInstance,
259
+ updateIntegration,
260
+ getPossibleIntegrations,
261
+ } = useCases;
51
262
  router.route('/api/integrations').get(
52
263
  catchAsyncError(async (req, res) => {
53
- const results = await integrationFactory.getIntegrationOptions();
54
- results.entities.authorized =
55
- await moduleFactory.getEntitiesForUser(getUserId(req));
56
- results.integrations =
57
- await IntegrationHelper.getIntegrationsForUserId(
58
- getUserId(req)
59
- );
264
+ const user = await authenticateUser.execute(req);
265
+ const userId = user.getId();
266
+ const integrations = await getIntegrationsForUser.execute(userId);
267
+ const results = {
268
+ entities: {
269
+ options: await getPossibleIntegrations.execute(),
270
+ authorized: await getEntitiesForUser.execute(userId),
271
+ },
272
+ integrations: integrations,
273
+ };
60
274
 
61
- for (const integrationRecord of results.integrations) {
62
- const integration =
63
- await integrationFactory.getInstanceFromIntegrationId({
64
- integrationId: integrationRecord.id,
65
- userId: getUserId(req),
66
- });
67
- integrationRecord.userActions = integration.userActions;
68
- }
69
275
  res.json(results);
70
276
  })
71
277
  );
72
278
 
73
279
  router.route('/api/integrations').post(
74
280
  catchAsyncError(async (req, res) => {
281
+ const user = await authenticateUser.execute(req);
282
+ const userId = user.getId();
75
283
  const params = checkRequiredParams(req.body, [
76
284
  'entities',
77
285
  'config',
78
286
  ]);
79
- // throw if not value
287
+
80
288
  get(params.config, 'type');
81
289
 
82
- // create integration
83
- const integration = await integrationFactory.createIntegration(
290
+ const integration = await createIntegration.execute(
84
291
  params.entities,
85
- getUserId(req),
292
+ userId,
86
293
  params.config
87
294
  );
88
295
 
89
- // post integration initialization
90
- debug(
91
- `Calling onCreate on the ${integration?.constructor?.Config?.name} Integration with no arguments`
92
- );
93
- await integration.send('ON_CREATE', {});
94
-
95
- res.status(201).json(
96
- await IntegrationHelper.getFormattedIntegration(
97
- integration.record
98
- )
99
- );
296
+ res.status(201).json(integration);
100
297
  })
101
298
  );
102
299
 
103
300
  router.route('/api/integrations/:integrationId').patch(
104
301
  catchAsyncError(async (req, res) => {
302
+ const user = await authenticateUser.execute(req);
303
+ const userId = user.getId();
105
304
  const params = checkRequiredParams(req.body, ['config']);
106
305
 
107
- const integration =
108
- await integrationFactory.getInstanceFromIntegrationId({
109
- integrationId: req.params.integrationId,
110
- userId: getUserId(req),
111
- });
112
-
113
- debug(
114
- `Calling onUpdate on the ${integration?.constructor?.Config?.name} Integration arguments: `,
115
- params
116
- );
117
- await integration.send('ON_UPDATE', params);
118
-
119
- res.json(
120
- await IntegrationHelper.getFormattedIntegration(
121
- integration.record
122
- )
306
+ const integration = await updateIntegration.execute(
307
+ req.params.integrationId,
308
+ userId,
309
+ params.config
123
310
  );
311
+ res.json(integration);
124
312
  })
125
313
  );
126
314
 
127
315
  router.route('/api/integrations/:integrationId').delete(
128
316
  catchAsyncError(async (req, res) => {
317
+ const user = await authenticateUser.execute(req);
129
318
  const params = checkRequiredParams(req.params, ['integrationId']);
130
- const integration =
131
- await integrationFactory.getInstanceFromIntegrationId({
132
- userId: getUserId(req),
133
- integrationId: params.integrationId,
134
- });
135
-
136
- debug(
137
- `Calling onUpdate on the ${integration?.constructor?.Definition?.name} Integration with no arguments`
319
+ await deleteIntegrationForUser.execute(
320
+ params.integrationId,
321
+ user.getId()
138
322
  );
139
- await integration.send('ON_DELETE');
140
- await IntegrationHelper.deleteIntegrationForUserById(
141
- getUserId(req),
142
- params.integrationId
143
- );
144
-
145
- res.status(201).json({});
323
+ res.status(204).json({});
146
324
  })
147
325
  );
148
326
 
149
327
  router.route('/api/integrations/:integrationId/config/options').get(
150
328
  catchAsyncError(async (req, res) => {
329
+ const user = await authenticateUser.execute(req);
151
330
  const params = checkRequiredParams(req.params, ['integrationId']);
152
- const integration =
153
- await integrationFactory.getInstanceFromIntegrationId(params);
331
+ const integration = await getIntegrationInstance.execute(
332
+ params.integrationId,
333
+ user.getId()
334
+ );
154
335
  res.json(await integration.send('GET_CONFIG_OPTIONS'));
155
336
  })
156
337
  );
@@ -159,13 +340,14 @@ function setIntegrationRoutes(router, factory, getUserId) {
159
340
  .route('/api/integrations/:integrationId/config/options/refresh')
160
341
  .post(
161
342
  catchAsyncError(async (req, res) => {
343
+ const user = await authenticateUser.execute(req);
162
344
  const params = checkRequiredParams(req.params, [
163
345
  'integrationId',
164
346
  ]);
165
- const integration =
166
- await integrationFactory.getInstanceFromIntegrationId(
167
- params
168
- );
347
+ const integration = await getIntegrationInstance.execute(
348
+ params.integrationId,
349
+ user.getId()
350
+ );
169
351
 
170
352
  res.json(
171
353
  await integration.send('REFRESH_CONFIG_OPTIONS', req.body)
@@ -174,9 +356,12 @@ function setIntegrationRoutes(router, factory, getUserId) {
174
356
  );
175
357
  router.route('/api/integrations/:integrationId/actions').all(
176
358
  catchAsyncError(async (req, res) => {
359
+ const user = await authenticateUser.execute(req);
177
360
  const params = checkRequiredParams(req.params, ['integrationId']);
178
- const integration =
179
- await integrationFactory.getInstanceFromIntegrationId(params);
361
+ const integration = await getIntegrationInstance.execute(
362
+ params.integrationId,
363
+ user.getId()
364
+ );
180
365
  res.json(await integration.send('GET_USER_ACTIONS', req.body));
181
366
  })
182
367
  );
@@ -185,14 +370,15 @@ function setIntegrationRoutes(router, factory, getUserId) {
185
370
  .route('/api/integrations/:integrationId/actions/:actionId/options')
186
371
  .all(
187
372
  catchAsyncError(async (req, res) => {
373
+ const user = await authenticateUser.execute(req);
188
374
  const params = checkRequiredParams(req.params, [
189
375
  'integrationId',
190
376
  'actionId',
191
377
  ]);
192
- const integration =
193
- await integrationFactory.getInstanceFromIntegrationId(
194
- params
195
- );
378
+ const integration = await getIntegrationInstance.execute(
379
+ params.integrationId,
380
+ user.getId()
381
+ );
196
382
 
197
383
  res.json(
198
384
  await integration.send('GET_USER_ACTION_OPTIONS', {
@@ -209,14 +395,15 @@ function setIntegrationRoutes(router, factory, getUserId) {
209
395
  )
210
396
  .post(
211
397
  catchAsyncError(async (req, res) => {
398
+ const user = await authenticateUser.execute(req);
212
399
  const params = checkRequiredParams(req.params, [
213
400
  'integrationId',
214
401
  'actionId',
215
402
  ]);
216
- const integration =
217
- await integrationFactory.getInstanceFromIntegrationId(
218
- params
219
- );
403
+ const integration = await getIntegrationInstance.execute(
404
+ params.integrationId,
405
+ user.getId()
406
+ );
220
407
 
221
408
  res.json(
222
409
  await integration.send('REFRESH_USER_ACTION_OPTIONS', {
@@ -229,23 +416,33 @@ function setIntegrationRoutes(router, factory, getUserId) {
229
416
 
230
417
  router.route('/api/integrations/:integrationId/actions/:actionId').post(
231
418
  catchAsyncError(async (req, res) => {
419
+ const user = await authenticateUser.execute(req);
232
420
  const params = checkRequiredParams(req.params, [
233
421
  'integrationId',
234
422
  'actionId',
235
423
  ]);
236
- const integration =
237
- await integrationFactory.getInstanceFromIntegrationId(params);
238
-
424
+ const integration = await getIntegrationInstance.execute(
425
+ params.integrationId,
426
+ user.getId()
427
+ );
239
428
  res.json(await integration.send(params.actionId, req.body));
240
429
  })
241
430
  );
242
431
 
243
432
  router.route('/api/integrations/:integrationId').get(
244
433
  catchAsyncError(async (req, res) => {
434
+ const user = await authenticateUser.execute(req);
435
+
436
+ if (!user) {
437
+ throw Boom.forbidden('User not found');
438
+ }
439
+
245
440
  const params = checkRequiredParams(req.params, ['integrationId']);
246
- const integration = await IntegrationHelper.getIntegrationById(
247
- params.integrationId
441
+ const integration = await getIntegrationInstance.execute(
442
+ params.integrationId,
443
+ user.getId()
248
444
  );
445
+
249
446
  // We could perhaps augment router with dynamic options? Haven't decided yet, but here may be the place
250
447
 
251
448
  res.json({
@@ -259,19 +456,20 @@ function setIntegrationRoutes(router, factory, getUserId) {
259
456
 
260
457
  router.route('/api/integrations/:integrationId/test-auth').get(
261
458
  catchAsyncError(async (req, res) => {
459
+ const user = await authenticateUser.execute(req);
262
460
  const params = checkRequiredParams(req.params, ['integrationId']);
263
- const instance =
264
- await integrationFactory.getInstanceFromIntegrationId({
265
- userId: getUserId(req),
266
- integrationId: params.integrationId,
267
- });
461
+ const instance = await getIntegrationInstance.execute(
462
+ params.integrationId,
463
+ user.getId()
464
+ );
268
465
 
269
466
  if (!instance) {
270
467
  throw Boom.notFound();
271
468
  }
272
469
 
273
470
  const start = Date.now();
274
- await instance.testAuth();
471
+ const authPassed = await instance.testAuth();
472
+ await instance.reconcileAuthStatus(authPassed);
275
473
  const errors = instance.record.messages?.errors?.filter(
276
474
  ({ timestamp }) => timestamp >= start
277
475
  );
@@ -286,57 +484,88 @@ function setIntegrationRoutes(router, factory, getUserId) {
286
484
  );
287
485
  }
288
486
 
289
- function setEntityRoutes(router, factory, getUserId) {
290
- const { moduleFactory, IntegrationHelper } = factory;
291
- const getModuleInstance = async (req, entityType) => {
292
- if (!moduleFactory.checkIsValidType(entityType)) {
293
- throw Boom.badRequest(
294
- `Error: Invalid entity type of ${entityType}, options are ${moduleFactory.moduleTypes.join(
295
- ', '
296
- )}`
297
- );
298
- }
299
- return await moduleFactory.getInstanceFromTypeName(
300
- entityType,
301
- getUserId(req)
302
- );
303
- };
487
+ /**
488
+ * Sets up entity-related routes for the integration router
489
+ * @param {Object} router - Express router instance
490
+ * @param {import('../user/use-cases/authenticate-user').AuthenticateUser} authenticateUser - Use case for multi-mode user authentication
491
+ */
492
+ function setEntityRoutes(router, authenticateUser, useCases) {
493
+ const {
494
+ getCredentialForUser,
495
+ getModuleInstanceFromType,
496
+ getEntityOptionsByType,
497
+ testModuleAuth,
498
+ getModule,
499
+ getEntityOptionsById,
500
+ refreshEntityOptions,
501
+ processAuthorizationCallback,
502
+ } = useCases;
304
503
 
305
504
  router.route('/api/authorize').get(
306
505
  catchAsyncError(async (req, res) => {
506
+ const user = await authenticateUser.execute(req);
507
+ const userId = user.getId();
307
508
  const params = checkRequiredParams(req.query, ['entityType']);
308
- const module = await getModuleInstance(req, params.entityType);
509
+ const module = await getModuleInstanceFromType.execute(
510
+ userId,
511
+ params.entityType,
512
+ { state: req.query.state }
513
+ );
309
514
  const areRequirementsValid =
310
515
  module.validateAuthorizationRequirements();
311
516
  if (!areRequirementsValid) {
312
517
  throw new Error(
313
- `Error: EntityManager of type ${params.entityType} requires a valid url`
518
+ `Error: Entity of type ${params.entityType} requires a valid url`
314
519
  );
315
520
  }
316
521
 
317
- res.json(await module.getAuthorizationRequirements());
522
+ res.json(module.getAuthorizationRequirements());
318
523
  })
319
524
  );
320
525
 
321
526
  router.route('/api/authorize').post(
322
527
  catchAsyncError(async (req, res) => {
528
+ const user = await authenticateUser.execute(req);
529
+ const userId = user.getId();
323
530
  const params = checkRequiredParams(req.body, [
324
531
  'entityType',
325
532
  'data',
326
533
  ]);
327
- const module = await getModuleInstance(req, params.entityType);
328
534
 
329
- res.json(
330
- await module.processAuthorizationCallback({
331
- userId: getUserId(req),
332
- data: params.data,
333
- })
535
+ const dataKeys =
536
+ params.data && typeof params.data === 'object'
537
+ ? Object.keys(params.data)
538
+ : [];
539
+ console.log(
540
+ `[Frigg] POST /api/authorize userId=${userId} entityType=${params.entityType} dataKeys=${JSON.stringify(dataKeys)}`
334
541
  );
542
+
543
+ try {
544
+ const entityDetails =
545
+ await processAuthorizationCallback.execute(
546
+ userId,
547
+ params.entityType,
548
+ params.data
549
+ );
550
+
551
+ console.log(
552
+ `[Frigg] POST /api/authorize success userId=${userId} entityType=${params.entityType} credentialId=${entityDetails?.credential_id} entityId=${entityDetails?.entity_id}`
553
+ );
554
+
555
+ res.json(entityDetails);
556
+ } catch (err) {
557
+ console.error(
558
+ `[Frigg] POST /api/authorize failed userId=${userId} entityType=${params.entityType} error=${err?.message || err}`
559
+ );
560
+ throw err;
561
+ }
335
562
  })
336
563
  );
337
564
 
338
565
  router.route('/api/entity').post(
339
566
  catchAsyncError(async (req, res) => {
567
+ const user = await authenticateUser.execute(req);
568
+ const userId = user.getId();
340
569
  const params = checkRequiredParams(req.body, [
341
570
  'entityType',
342
571
  'data',
@@ -344,20 +573,24 @@ function setEntityRoutes(router, factory, getUserId) {
344
573
  checkRequiredParams(req.body.data, ['credential_id']);
345
574
 
346
575
  // May want to pass along the user ID as well so credential ID's can't be fished???
347
- const credential = await IntegrationHelper.getCredentialById(
348
- params.data.credential_id
576
+ const credential = await getCredentialForUser.execute(
577
+ params.data.credential_id,
578
+ userId
349
579
  );
350
580
 
351
581
  if (!credential) {
352
582
  throw Boom.badRequest('Invalid credential ID');
353
583
  }
354
584
 
355
- const module = await getModuleInstance(req, params.entityType);
585
+ const module = await getModuleInstanceFromType.execute(
586
+ userId,
587
+ params.entityType
588
+ );
356
589
  const entityDetails = await module.getEntityDetails(
357
590
  module.api,
358
591
  null,
359
592
  null,
360
- getUserId(req)
593
+ userId
361
594
  );
362
595
 
363
596
  res.json(await module.findOrCreateEntity(entityDetails));
@@ -366,43 +599,44 @@ function setEntityRoutes(router, factory, getUserId) {
366
599
 
367
600
  router.route('/api/entity/options/:credentialId').get(
368
601
  catchAsyncError(async (req, res) => {
602
+ const user = await authenticateUser.execute(req);
603
+ const userId = user.getId();
369
604
  // TODO May want to pass along the user ID as well so credential ID's can't be fished???
370
605
  // TODO **flagging this for review** -MW
371
- const credential = await IntegrationHelper.getCredentialById(
372
- req.params.credentialId
606
+ const credential = await getCredentialForUser.execute(
607
+ req.params.credentialId,
608
+ userId
373
609
  );
374
- if (credential.user._id.toString() !== getUserId(req)) {
610
+ if (credential.userId.toString() !== userId) {
375
611
  throw Boom.forbidden('Credential does not belong to user');
376
612
  }
377
613
 
378
614
  const params = checkRequiredParams(req.query, ['entityType']);
379
- const module = await getModuleInstance(req, params.entityType);
615
+ const entityOptions = await getEntityOptionsByType.execute(
616
+ userId,
617
+ params.entityType
618
+ );
380
619
 
381
- res.json(await module.getEntityOptions());
620
+ res.json(entityOptions);
382
621
  })
383
622
  );
384
623
 
385
624
  router.route('/api/entities/:entityId/test-auth').get(
386
625
  catchAsyncError(async (req, res) => {
626
+ const user = await authenticateUser.execute(req);
387
627
  const params = checkRequiredParams(req.params, ['entityId']);
388
- const module = await moduleFactory.getModuleInstanceFromEntityId(
628
+ const testAuthResponse = await testModuleAuth.execute(
389
629
  params.entityId,
390
- getUserId(req)
630
+ user // Pass User object for proper validation
391
631
  );
392
632
 
393
- if (!module) {
394
- throw Boom.notFound();
395
- }
396
-
397
- const testAuthResponse = await module.testAuth();
398
-
399
633
  if (!testAuthResponse) {
400
634
  res.status(400);
401
635
  res.json({
402
636
  errors: [
403
637
  {
404
638
  title: 'Authentication Error',
405
- message: `There was an error with your ${module.getName()} Entity. Please reconnect/re-authenticate, or reach out to Support for assistance.`,
639
+ message: `There was an error with your Entity. Please reconnect/re-authenticate, or reach out to Support for assistance.`,
406
640
  timestamp: Date.now(),
407
641
  },
408
642
  ],
@@ -415,55 +649,39 @@ function setEntityRoutes(router, factory, getUserId) {
415
649
 
416
650
  router.route('/api/entities/:entityId').get(
417
651
  catchAsyncError(async (req, res) => {
652
+ const user = await authenticateUser.execute(req);
418
653
  const params = checkRequiredParams(req.params, ['entityId']);
419
- const module = await moduleFactory.getModuleInstanceFromEntityId(
420
- params.entityId,
421
- getUserId(req)
422
- );
654
+ const module = await getModule.execute(params.entityId, user); // Pass User object
423
655
 
424
- if (!module) {
425
- throw Boom.notFound();
426
- }
427
-
428
- res.json(module.entity);
656
+ res.json(module);
429
657
  })
430
658
  );
431
659
 
432
660
  router.route('/api/entities/:entityId/options').post(
433
661
  catchAsyncError(async (req, res) => {
434
- const params = checkRequiredParams(req.params, [
435
- 'entityId',
436
- getUserId(req),
437
- ]);
438
- const module = await moduleFactory.getModuleInstanceFromEntityId(
662
+ const user = await authenticateUser.execute(req);
663
+ const params = checkRequiredParams(req.params, ['entityId']);
664
+
665
+ const entityOptions = await getEntityOptionsById.execute(
439
666
  params.entityId,
440
- getUserId(req)
667
+ user // Pass User object
441
668
  );
442
669
 
443
- if (!module) {
444
- throw Boom.notFound();
445
- }
446
-
447
- res.json(await module.getEntityOptions());
670
+ res.json(entityOptions);
448
671
  })
449
672
  );
450
673
 
451
674
  router.route('/api/entities/:entityId/options/refresh').post(
452
675
  catchAsyncError(async (req, res) => {
453
- const params = checkRequiredParams(req.params, [
454
- 'entityId',
455
- getUserId(req),
456
- ]);
457
- const module = await moduleFactory.getModuleInstanceFromEntityId(
676
+ const user = await authenticateUser.execute(req);
677
+ const params = checkRequiredParams(req.params, ['entityId']);
678
+ const updatedOptions = await refreshEntityOptions.execute(
458
679
  params.entityId,
459
- getUserId(req)
680
+ user, // Pass User object
681
+ req.body
460
682
  );
461
683
 
462
- if (!module) {
463
- throw Boom.notFound();
464
- }
465
-
466
- res.json(await module.refreshEntityOptions(req.body));
684
+ res.json(updatedOptions);
467
685
  })
468
686
  );
469
687
  }