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