@friggframework/core 2.0.0--canary.703.12b980b.0 → 2.0.0--canary.707.df80bfd.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/CLAUDE.md +28 -0
- package/README.md +105 -0
- package/application/commands/integration-commands.js +20 -10
- package/application/commands/scheduler-commands.js +11 -7
- package/application/commands/user-commands.js +17 -5
- package/application/index.js +6 -2
- package/core/Worker.js +31 -7
- package/core/create-handler.js +9 -0
- package/credential/repositories/credential-repository-documentdb.js +34 -0
- package/credential/repositories/credential-repository-interface.js +15 -0
- package/credential/repositories/credential-repository-mongo.js +23 -0
- package/credential/repositories/credential-repository-postgres.js +28 -0
- package/credential/use-cases/credential-operations-for-user.js +202 -0
- package/credential/use-cases/reauthorize-credential-for-user.js +73 -0
- package/database/config.js +48 -24
- package/database/documentdb-encryption-service.js +9 -22
- package/database/documentdb-utils.js +2 -2
- package/database/encryption/README.md +78 -14
- package/database/encryption/documentdb-encryption-service.md +78 -1
- package/database/encryption/encryption-config.js +219 -0
- package/database/encryption/encryption-schema-registry.js +121 -24
- package/database/encryption/field-encryption-service.js +69 -5
- package/database/encryption/integration-mapping-encryption.js +1 -1
- package/database/encryption/test-support/fake-ciphertext.js +15 -0
- package/database/organization-where.js +18 -0
- package/database/prisma.js +15 -38
- package/database/unique-violation.js +25 -0
- package/database/use-cases/check-encryption-health-use-case.js +43 -52
- package/errors/index.js +0 -4
- package/extensions/bootstrap-runner.js +43 -0
- package/extensions/extension-loader.js +230 -0
- package/extensions/index.js +44 -0
- package/extensions/initialize-app.js +123 -0
- package/extensions/prisma-composer.js +270 -0
- package/extensions/route-mounter.js +103 -0
- package/extensions/schema-composer.js +188 -0
- package/generated/prisma-mongodb/edge.js +33 -42
- package/generated/prisma-mongodb/index-browser.js +30 -39
- package/generated/prisma-mongodb/index.d.ts +3187 -2005
- package/generated/prisma-mongodb/index.js +33 -42
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +86 -59
- package/generated/prisma-mongodb/wasm.js +33 -42
- package/generated/prisma-postgresql/edge.js +33 -42
- package/generated/prisma-postgresql/index-browser.js +30 -39
- package/generated/prisma-postgresql/index.d.ts +3380 -2177
- package/generated/prisma-postgresql/index.js +33 -42
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +81 -57
- package/generated/prisma-postgresql/wasm.js +33 -42
- package/handlers/WEBHOOKS.md +0 -29
- package/handlers/app-definition-loader.js +128 -19
- package/handlers/app-handler-helpers.js +27 -8
- package/handlers/backend-utils.js +31 -25
- package/handlers/integration-event-dispatcher.js +3 -7
- package/handlers/middleware/admin-auth.js +14 -1
- package/handlers/routers/auth.js +46 -10
- package/handlers/routers/health.js +13 -4
- package/handlers/routers/integration-defined-routers.js +144 -92
- package/handlers/routers/integration-webhook-routers.js +100 -50
- package/handlers/workers/integration-defined-workers.js +5 -2
- package/index.js +66 -16
- package/infrastructure/scheduler/index.js +19 -6
- package/infrastructure/scheduler/netlify-scheduler-adapter.js +216 -0
- package/infrastructure/scheduler/scheduled-job-repository.js +118 -0
- package/infrastructure/scheduler/scheduler-service-factory.js +55 -7
- package/integrations/index.js +1 -14
- package/integrations/integration-base.js +2 -163
- package/integrations/integration-router.js +132 -102
- package/integrations/repositories/integration-mapping-repository-documentdb.js +0 -50
- package/integrations/repositories/integration-mapping-repository-interface.js +0 -15
- package/integrations/repositories/integration-mapping-repository-mongo.js +0 -29
- package/integrations/repositories/integration-mapping-repository-postgres.js +0 -30
- package/integrations/repositories/integration-mapping-repository.js +0 -29
- package/integrations/repositories/integration-not-found.js +14 -0
- package/integrations/repositories/integration-repository-documentdb.js +37 -9
- package/integrations/repositories/integration-repository-interface.js +17 -4
- package/integrations/repositories/integration-repository-mongo.js +64 -96
- package/integrations/repositories/integration-repository-postgres.js +63 -81
- package/integrations/repositories/process-repository-mongo.js +1 -1
- package/integrations/schedule-config.js +80 -0
- package/integrations/tests/doubles/test-integration-repository.js +12 -1
- package/integrations/use-cases/create-integration.js +56 -31
- package/integrations/use-cases/delete-integration-for-user.js +4 -4
- package/integrations/use-cases/dispatch-ongoing-syncs.js +100 -0
- package/integrations/use-cases/get-integration-for-user.js +2 -4
- package/integrations/use-cases/get-integration-instance.js +4 -4
- package/integrations/use-cases/get-integrations-for-user.js +79 -39
- package/integrations/use-cases/get-possible-integrations.js +2 -7
- package/integrations/use-cases/index.js +7 -1
- package/integrations/use-cases/integration-operations-for-user.js +256 -0
- package/integrations/use-cases/resolve-integration-ownership.js +177 -0
- package/integrations/use-cases/update-integration.js +4 -4
- package/integrations/utils/map-integration-dto.js +43 -14
- package/management-api/create-management-api-router.js +49 -0
- package/management-api/error-response.js +116 -0
- package/management-api/management-api-config.js +151 -0
- package/management-api/meta-router.js +76 -0
- package/management-api/openapi/build-openapi.js +144 -0
- package/management-api/openapi/components.js +415 -0
- package/management-api/openapi/v1-operations.js +83 -0
- package/management-api/openapi/v2-operations.js +264 -0
- package/management-api/route-registry.js +411 -0
- package/management-api/test-support/http-client.js +39 -0
- package/management-api/use-cases/get-management-api-meta.js +57 -0
- package/management-api/v1-deprecation.js +120 -0
- package/management-api/v2/create-v2-router.js +85 -0
- package/management-api/v2/dependencies.js +281 -0
- package/management-api/v2/dto.js +143 -0
- package/management-api/v2/handlers/authorization.js +94 -0
- package/management-api/v2/handlers/credentials.js +33 -0
- package/management-api/v2/handlers/entities.js +77 -0
- package/management-api/v2/handlers/integrations.js +128 -0
- package/management-api/v2/handlers/proxy.js +34 -0
- package/management-api/v2/request.js +85 -0
- package/management-api/v2/test-support/fake-dependencies.js +103 -0
- package/modules/domain/authorization-session.js +144 -0
- package/modules/entity-scope.js +15 -0
- package/modules/entity-type-registry.js +311 -0
- package/modules/index.js +14 -0
- package/modules/module-factory.js +12 -0
- package/modules/module.js +53 -2
- package/modules/proxy/proxy-bases.js +169 -0
- package/modules/proxy/proxy-errors.js +31 -0
- package/modules/proxy/proxy-path.js +183 -0
- package/modules/proxy/proxy-policy.js +277 -0
- package/modules/repositories/authorization-session-repository-documentdb.js +112 -0
- package/modules/repositories/authorization-session-repository-factory.js +31 -0
- package/modules/repositories/authorization-session-repository-interface.js +47 -0
- package/modules/repositories/authorization-session-repository-prisma.js +87 -0
- package/modules/repositories/entity-not-found.js +18 -0
- package/modules/repositories/module-repository-documentdb.js +51 -6
- package/modules/repositories/module-repository-interface.js +19 -2
- package/modules/repositories/module-repository-mongo.js +67 -74
- package/modules/repositories/module-repository-postgres.js +66 -74
- package/modules/repositories/module-repository.js +2 -1
- package/modules/requester/proxy-request.js +245 -0
- package/modules/requester/requester.js +35 -5
- package/modules/scope-config.js +192 -0
- package/modules/scope-policy.js +112 -0
- package/modules/scope-resolution.js +288 -0
- package/modules/scope-visibility.js +247 -0
- package/modules/tests/doubles/in-memory-authorization-session-repository.js +45 -0
- package/modules/tests/doubles/ownership-matching.js +18 -0
- package/modules/use-cases/authorize-entity-for-user.js +61 -0
- package/modules/use-cases/create-entity-from-credential.js +113 -0
- package/modules/use-cases/entity-operations-for-user.js +162 -0
- package/modules/use-cases/entity-types.js +139 -0
- package/modules/use-cases/execute-entity-proxy-request.js +331 -0
- package/modules/use-cases/get-authorization-requirements.js +100 -0
- package/modules/use-cases/get-entities-for-user.js +26 -13
- package/modules/use-cases/get-entity-module-for-user.js +113 -0
- package/modules/use-cases/get-entity-options-by-id.js +10 -4
- package/modules/use-cases/get-entity-options-by-type.js +1 -1
- package/modules/use-cases/get-module-instance-from-type.js +1 -1
- package/modules/use-cases/get-module.js +10 -4
- package/modules/use-cases/manage-access.js +21 -0
- package/modules/use-cases/multi-step-authorization.js +329 -0
- package/modules/use-cases/process-authorization-callback.js +53 -19
- package/modules/use-cases/refresh-entity-options.js +10 -4
- package/modules/use-cases/test-module-auth.js +10 -4
- package/package.json +6 -7
- package/prisma-mongodb/schema.prisma +86 -59
- package/prisma-postgresql/migrations/20261003000000_add_authorization_session/migration.sql +28 -0
- package/prisma-postgresql/migrations/20261015000000_add_organization_membership/migration.sql +26 -0
- package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +25 -0
- package/prisma-postgresql/migrations/20261017000000_add_scheduled_job/migration.sql +28 -0
- package/prisma-postgresql/schema.prisma +81 -57
- package/providers/index.js +23 -0
- package/providers/resolve-provider.js +93 -0
- package/providers/runtime-detection.js +124 -0
- package/queues/index.js +25 -0
- package/queues/providers/index.js +11 -0
- package/queues/providers/netlify-background-provider.js +150 -0
- package/queues/providers/qstash-queue-provider.js +219 -0
- package/queues/providers/sqs-queue-provider.js +70 -0
- package/queues/queue-client-interface.js +55 -0
- package/queues/queue-message-auth.js +193 -0
- package/queues/queue-provider-factory.js +101 -0
- package/queues/queue-provider.js +65 -0
- package/queues/queuer-util.js +2 -9
- package/queues/sqs-queue-client.js +81 -0
- package/types/index.d.ts +2 -0
- package/types/modules/index.d.ts +214 -0
- package/types/user/index.d.ts +134 -0
- package/user/adopter-jwt-config.js +177 -0
- package/user/adopter-jwt-errors.js +59 -0
- package/user/adopter-token-verifier.js +122 -0
- package/user/app-user-helpers.js +97 -0
- package/user/create-user-authentication.js +64 -0
- package/user/membership.js +51 -0
- package/user/repositories/organization-membership-record.js +19 -0
- package/user/repositories/organization-membership-repository-documentdb.js +106 -0
- package/user/repositories/organization-membership-repository-factory.js +42 -0
- package/user/repositories/organization-membership-repository-interface.js +57 -0
- package/user/repositories/organization-membership-repository-mongo.js +13 -0
- package/user/repositories/organization-membership-repository-postgres.js +29 -0
- package/user/repositories/organization-membership-repository-prisma.js +81 -0
- package/user/repositories/user-repository-documentdb.js +27 -2
- package/user/repositories/user-repository-interface.js +18 -0
- package/user/repositories/user-repository-mongo.js +24 -0
- package/user/repositories/user-repository-postgres.js +18 -0
- package/user/tests/doubles/adopter-jwt-fixtures.js +220 -0
- package/user/use-cases/authenticate-user.js +7 -1
- package/user/use-cases/ensure-organization-membership.js +92 -0
- package/user/use-cases/find-individual-users-by-organization.js +54 -0
- package/user/use-cases/get-user-from-adopter-jwt.js +95 -124
- package/user/use-cases/get-user-from-x-frigg-headers.js +83 -80
- package/user/user.js +64 -1
- package/errors/mapping-already-exists-error.js +0 -14
- package/handlers/workers/integration-triggers.js +0 -25
- package/infrastructure/scheduler/recurrence.js +0 -204
- package/integrations/define/DESIGN.md +0 -122
- package/integrations/define/config.js +0 -98
- package/integrations/define/define-app.js +0 -66
- package/integrations/define/define-extension.js +0 -154
- package/integrations/define/define-integration.js +0 -335
- package/integrations/define/examples/deal-alerts.js +0 -140
- package/integrations/define/extension-binding.js +0 -174
- package/integrations/define/index.js +0 -11
- package/integrations/define/json-schema-lite.js +0 -68
- package/integrations/define/subscriptions.js +0 -186
- package/integrations/define/tests/fixtures/hubspot.js +0 -109
- package/integrations/define/tests/fixtures/slack.js +0 -26
- package/integrations/define/use.js +0 -39
- package/integrations/definitions/README.md +0 -278
- package/integrations/definitions/canonical.js +0 -11
- package/integrations/definitions/capabilities/AUDIT.md +0 -480
- package/integrations/definitions/capabilities/acmeerp.capabilities.json +0 -633
- package/integrations/definitions/capabilities/asana.capabilities.json +0 -279
- package/integrations/definitions/capabilities/calendly.capabilities.json +0 -385
- package/integrations/definitions/capabilities/docusign.capabilities.json +0 -314
- package/integrations/definitions/capabilities/fathom.capabilities.json +0 -238
- package/integrations/definitions/capabilities/github.capabilities.json +0 -585
- package/integrations/definitions/capabilities/hubspot.capabilities.json +0 -822
- package/integrations/definitions/capabilities/jira.capabilities.json +0 -391
- package/integrations/definitions/capabilities/klaviyo.capabilities.json +0 -503
- package/integrations/definitions/capabilities/linear.capabilities.json +0 -378
- package/integrations/definitions/capabilities/netsuite.capabilities.json +0 -535
- package/integrations/definitions/capabilities/notion.capabilities.json +0 -208
- package/integrations/definitions/capabilities/phone.capabilities.json +0 -511
- package/integrations/definitions/capabilities/pipedrive.capabilities.json +0 -430
- package/integrations/definitions/capabilities/quickbooks.capabilities.json +0 -635
- package/integrations/definitions/capabilities/salesforce.capabilities.json +0 -568
- package/integrations/definitions/capabilities/shopify.capabilities.json +0 -1128
- package/integrations/definitions/capabilities/slack.capabilities.json +0 -373
- package/integrations/definitions/capabilities/stripe.capabilities.json +0 -630
- package/integrations/definitions/capabilities/webflow.capabilities.json +0 -196
- package/integrations/definitions/capabilities/zendesk.capabilities.json +0 -422
- package/integrations/definitions/compile.js +0 -80
- package/integrations/definitions/config-form.js +0 -137
- package/integrations/definitions/examples/acme-erp-quickbooks.definition.json +0 -467
- package/integrations/definitions/examples/asana-slack.definition.json +0 -219
- package/integrations/definitions/examples/calendly-salesforce.definition.json +0 -459
- package/integrations/definitions/examples/docusign-salesforce.definition.json +0 -305
- package/integrations/definitions/examples/fathom-hubspot-notion.definition.json +0 -575
- package/integrations/definitions/examples/github-linear.definition.json +0 -322
- package/integrations/definitions/examples/hubspot-slack.definition.json +0 -427
- package/integrations/definitions/examples/klaviyo-hubspot.definition.json +0 -336
- package/integrations/definitions/examples/phone-hubspot.definition.json +0 -633
- package/integrations/definitions/examples/pipedrive-hubspot.definition.json +0 -136
- package/integrations/definitions/examples/pipedrive-phone.definition.json +0 -340
- package/integrations/definitions/examples/records/phone-hubspot.definition-version.json +0 -652
- package/integrations/definitions/examples/records/phone-hubspot.integration.json +0 -86
- package/integrations/definitions/examples/records/phone-hubspot.mappings.json +0 -39
- package/integrations/definitions/examples/records/phone-hubspot.workflow-run.json +0 -62
- package/integrations/definitions/examples/shopify-klaviyo.definition.json +0 -488
- package/integrations/definitions/examples/shopify-netsuite.definition.json +0 -622
- package/integrations/definitions/examples/stripe-quickbooks.definition.json +0 -476
- package/integrations/definitions/examples/webflow-hubspot-slack.definition.json +0 -262
- package/integrations/definitions/examples/zendesk-jira.definition.json +0 -604
- package/integrations/definitions/expressions.js +0 -229
- package/integrations/definitions/index.js +0 -48
- package/integrations/definitions/integration-runtime.js +0 -779
- package/integrations/definitions/interpreter.js +0 -104
- package/integrations/definitions/manifests.js +0 -177
- package/integrations/definitions/renderers/common.js +0 -67
- package/integrations/definitions/renderers/html.js +0 -129
- package/integrations/definitions/renderers/hubspot.js +0 -59
- package/integrations/definitions/renderers/preview.js +0 -154
- package/integrations/definitions/renderers/slack.js +0 -146
- package/integrations/definitions/repositories/definition-version-repository.js +0 -67
- package/integrations/definitions/repositories/workflow-run-repository.js +0 -80
- package/integrations/definitions/router.js +0 -170
- package/integrations/definitions/runtime.js +0 -268
- package/integrations/definitions/schema/capability-manifest.v0.1.schema.json +0 -549
- package/integrations/definitions/schema/installation.v0.1.schema.json +0 -130
- package/integrations/definitions/schema/integration-definition.v0.1.schema.json +0 -909
- package/integrations/definitions/schema/records.md +0 -105
- package/integrations/definitions/schema-check.js +0 -58
- package/integrations/definitions/scripts/check-manifests.js +0 -220
- package/integrations/definitions/scripts/validate.js +0 -66
- package/integrations/definitions/steps.js +0 -123
- package/integrations/definitions/sync-engine.js +0 -297
- package/integrations/definitions/tests/helpers-fake-crm.js +0 -49
- package/integrations/definitions/transforms.js +0 -91
- package/integrations/definitions/use-cases/definition-use-cases.js +0 -245
- package/integrations/definitions/validate.js +0 -436
- package/integrations/definitions/versioning.js +0 -176
- package/integrations/definitions/webhooks.js +0 -119
- package/integrations/integration-types.js +0 -73
- package/integrations/triggers.js +0 -244
- package/integrations/use-cases/run-trigger-tick.js +0 -155
- package/integrations/use-cases/run-trigger.js +0 -77
- package/prisma-postgresql/migrations/20261018000000_add_data_defined_integrations/migration.sql +0 -66
- package/prisma-postgresql/migrations/20261019000000_workflow_run_waits/migration.sql +0 -7
- package/prisma-postgresql/migrations/20261019120000_definition_workspace/migration.sql +0 -5
|
@@ -31,9 +31,6 @@ const {
|
|
|
31
31
|
GetIntegrationInstance,
|
|
32
32
|
} = require('./use-cases/get-integration-instance');
|
|
33
33
|
const { UpdateIntegration } = require('./use-cases/update-integration');
|
|
34
|
-
const {
|
|
35
|
-
getModulesDefinitionFromIntegrationClasses,
|
|
36
|
-
} = require('./utils/map-integration-dto');
|
|
37
34
|
const {
|
|
38
35
|
GetModuleInstanceFromType,
|
|
39
36
|
} = require('../modules/use-cases/get-module-instance-from-type');
|
|
@@ -54,47 +51,51 @@ const {
|
|
|
54
51
|
const {
|
|
55
52
|
createUserRepository,
|
|
56
53
|
} = 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
54
|
const {
|
|
67
55
|
AuthenticateWithSharedSecret,
|
|
68
56
|
} = require('../user/use-cases/authenticate-with-shared-secret');
|
|
69
57
|
const { AuthenticateUser } = require('../user/use-cases/authenticate-user');
|
|
58
|
+
const {
|
|
59
|
+
buildUserAuthentication,
|
|
60
|
+
} = require('../user/create-user-authentication');
|
|
70
61
|
const {
|
|
71
62
|
ProcessAuthorizationCallback,
|
|
72
63
|
} = require('../modules/use-cases/process-authorization-callback');
|
|
64
|
+
const { createScopePolicy } = require('../modules/scope-policy');
|
|
65
|
+
const {
|
|
66
|
+
AuthorizeEntityForUser,
|
|
67
|
+
} = require('../modules/use-cases/authorize-entity-for-user');
|
|
68
|
+
const {
|
|
69
|
+
CreateEntityFromCredential,
|
|
70
|
+
} = require('../modules/use-cases/create-entity-from-credential');
|
|
71
|
+
const {
|
|
72
|
+
ResolveIntegrationOwnership,
|
|
73
|
+
} = require('./use-cases/resolve-integration-ownership');
|
|
74
|
+
const { GetOwnedIntegrationRecord } = require('./use-cases/integration-operations-for-user');
|
|
73
75
|
|
|
74
76
|
const log = getLogger('frigg.integrations');
|
|
75
77
|
|
|
76
78
|
function createIntegrationRouter() {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
// moduleDefinitions is the app registry's definitions (ADR-059), so
|
|
80
|
+
// /api/authorize and friends accept a type no integration binds.
|
|
81
|
+
const {
|
|
82
|
+
integrations: integrationClasses,
|
|
83
|
+
userConfig,
|
|
84
|
+
moduleDefinitions,
|
|
85
|
+
ownership,
|
|
86
|
+
entityTypeRegistry,
|
|
87
|
+
} = loadAppDefinition();
|
|
88
|
+
// Ownership by scope (ADR-056 §3): one object every use case asks.
|
|
89
|
+
const scopePolicy = createScopePolicy({ ownership, entityTypeRegistry });
|
|
79
90
|
const moduleRepository = createModuleRepository();
|
|
80
91
|
const integrationRepository = createIntegrationRepository();
|
|
81
92
|
const credentialRepository = createCredentialRepository();
|
|
82
93
|
const userRepository = createUserRepository();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const getUserFromXFriggHeaders = new GetUserFromXFriggHeaders({
|
|
90
|
-
userRepository,
|
|
91
|
-
userConfig,
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
const getUserFromAdopterJwt = new GetUserFromAdopterJwt({
|
|
95
|
-
userRepository,
|
|
96
|
-
userConfig,
|
|
97
|
-
});
|
|
94
|
+
const {
|
|
95
|
+
getUserFromBearerToken,
|
|
96
|
+
getUserFromXFriggHeaders,
|
|
97
|
+
getUserFromAdopterJwt,
|
|
98
|
+
} = buildUserAuthentication({ userConfig, userRepository });
|
|
98
99
|
|
|
99
100
|
const authenticateWithSharedSecret = new AuthenticateWithSharedSecret();
|
|
100
101
|
|
|
@@ -108,8 +109,7 @@ function createIntegrationRouter() {
|
|
|
108
109
|
|
|
109
110
|
const moduleFactory = new ModuleFactory({
|
|
110
111
|
moduleRepository,
|
|
111
|
-
moduleDefinitions
|
|
112
|
-
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
112
|
+
moduleDefinitions,
|
|
113
113
|
});
|
|
114
114
|
const deleteIntegrationForUser = new DeleteIntegrationForUser({
|
|
115
115
|
integrationRepository,
|
|
@@ -122,6 +122,19 @@ function createIntegrationRouter() {
|
|
|
122
122
|
integrationClasses,
|
|
123
123
|
moduleFactory,
|
|
124
124
|
moduleRepository,
|
|
125
|
+
scopePolicy,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Decides who owns a new integration and which entities the caller may bind
|
|
129
|
+
// (the v1 create used to check neither), and who may reach an existing one.
|
|
130
|
+
const resolveIntegrationOwnership = new ResolveIntegrationOwnership({
|
|
131
|
+
moduleRepository,
|
|
132
|
+
integrationClasses,
|
|
133
|
+
scopePolicy,
|
|
134
|
+
});
|
|
135
|
+
const getOwnedIntegrationRecord = new GetOwnedIntegrationRecord({
|
|
136
|
+
integrationRepository,
|
|
137
|
+
scopePolicy,
|
|
125
138
|
});
|
|
126
139
|
|
|
127
140
|
const getCredentialForUser = new GetCredentialForUser({
|
|
@@ -136,8 +149,8 @@ function createIntegrationRouter() {
|
|
|
136
149
|
|
|
137
150
|
const getEntitiesForUser = new GetEntitiesForUser({
|
|
138
151
|
moduleRepository,
|
|
139
|
-
moduleDefinitions
|
|
140
|
-
|
|
152
|
+
moduleDefinitions,
|
|
153
|
+
scopePolicy,
|
|
141
154
|
});
|
|
142
155
|
|
|
143
156
|
const getIntegrationInstance = new GetIntegrationInstance({
|
|
@@ -153,54 +166,65 @@ function createIntegrationRouter() {
|
|
|
153
166
|
});
|
|
154
167
|
|
|
155
168
|
const getModuleInstanceFromType = new GetModuleInstanceFromType({
|
|
156
|
-
moduleDefinitions
|
|
157
|
-
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
169
|
+
moduleDefinitions,
|
|
158
170
|
});
|
|
159
171
|
|
|
160
172
|
const getEntityOptionsByType = new GetEntityOptionsByType({
|
|
161
|
-
moduleDefinitions
|
|
162
|
-
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
173
|
+
moduleDefinitions,
|
|
163
174
|
});
|
|
164
175
|
|
|
165
176
|
const testModuleAuth = new TestModuleAuth({
|
|
166
177
|
moduleRepository,
|
|
167
|
-
moduleDefinitions
|
|
168
|
-
|
|
178
|
+
moduleDefinitions,
|
|
179
|
+
scopePolicy,
|
|
169
180
|
});
|
|
170
181
|
|
|
171
182
|
const getModule = new GetModule({
|
|
172
183
|
moduleRepository,
|
|
173
|
-
moduleDefinitions
|
|
174
|
-
|
|
184
|
+
moduleDefinitions,
|
|
185
|
+
scopePolicy,
|
|
175
186
|
});
|
|
176
187
|
|
|
177
188
|
const getEntityOptionsById = new GetEntityOptionsById({
|
|
178
189
|
moduleRepository,
|
|
179
|
-
moduleDefinitions
|
|
180
|
-
|
|
190
|
+
moduleDefinitions,
|
|
191
|
+
scopePolicy,
|
|
181
192
|
});
|
|
182
193
|
|
|
183
194
|
const refreshEntityOptions = new RefreshEntityOptions({
|
|
184
195
|
moduleRepository,
|
|
185
|
-
moduleDefinitions
|
|
186
|
-
|
|
196
|
+
moduleDefinitions,
|
|
197
|
+
scopePolicy,
|
|
187
198
|
});
|
|
188
199
|
|
|
189
200
|
const getPossibleIntegrations = new GetPossibleIntegrations({
|
|
190
201
|
integrationClasses,
|
|
191
202
|
});
|
|
192
203
|
|
|
204
|
+
// The owner of what an authorization creates follows its scope (ADR-056 §3.2).
|
|
193
205
|
const processAuthorizationCallback = new ProcessAuthorizationCallback({
|
|
194
206
|
moduleRepository,
|
|
195
207
|
credentialRepository,
|
|
196
208
|
integrationRepository,
|
|
197
|
-
moduleDefinitions
|
|
198
|
-
|
|
209
|
+
moduleDefinitions,
|
|
210
|
+
});
|
|
211
|
+
const authorizeEntityForUser = new AuthorizeEntityForUser({
|
|
212
|
+
scopePolicy,
|
|
213
|
+
processAuthorizationCallback,
|
|
214
|
+
});
|
|
215
|
+
// v1 POST /api/entity: same owner resolution as /api/authorize.
|
|
216
|
+
const createEntityFromCredential = new CreateEntityFromCredential({
|
|
217
|
+
authorizeEntityForUser,
|
|
218
|
+
processAuthorizationCallback,
|
|
219
|
+
credentialRepository,
|
|
220
|
+
moduleDefinitions,
|
|
199
221
|
});
|
|
200
222
|
|
|
201
223
|
const router = express();
|
|
202
224
|
|
|
203
225
|
setIntegrationRoutes(router, authenticateUser, {
|
|
226
|
+
resolveIntegrationOwnership,
|
|
227
|
+
getOwnedIntegrationRecord,
|
|
204
228
|
createIntegration,
|
|
205
229
|
deleteIntegrationForUser,
|
|
206
230
|
getIntegrationsForUser,
|
|
@@ -209,11 +233,6 @@ function createIntegrationRouter() {
|
|
|
209
233
|
updateIntegration,
|
|
210
234
|
getPossibleIntegrations,
|
|
211
235
|
});
|
|
212
|
-
// Integration versions, run history, sync progress and approvals (ADR-063): mounted when the app registers the integration runtime.
|
|
213
|
-
require('./definitions/router').setIntegrationRuntimeRoutes(router, authenticateUser, {
|
|
214
|
-
getIntegrationInstance,
|
|
215
|
-
integrationClasses,
|
|
216
|
-
});
|
|
217
236
|
setEntityRoutes(router, authenticateUser, {
|
|
218
237
|
getCredentialForUser,
|
|
219
238
|
getModuleInstanceFromType,
|
|
@@ -222,7 +241,8 @@ function createIntegrationRouter() {
|
|
|
222
241
|
getModule,
|
|
223
242
|
getEntityOptionsById,
|
|
224
243
|
refreshEntityOptions,
|
|
225
|
-
|
|
244
|
+
authorizeEntityForUser,
|
|
245
|
+
createEntityFromCredential,
|
|
226
246
|
});
|
|
227
247
|
return router;
|
|
228
248
|
}
|
|
@@ -259,6 +279,8 @@ function checkRequiredParams(params, requiredKeys) {
|
|
|
259
279
|
*/
|
|
260
280
|
function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
261
281
|
const {
|
|
282
|
+
resolveIntegrationOwnership,
|
|
283
|
+
getOwnedIntegrationRecord,
|
|
262
284
|
createIntegration,
|
|
263
285
|
deleteIntegrationForUser,
|
|
264
286
|
getIntegrationsForUser,
|
|
@@ -267,15 +289,22 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
267
289
|
updateIntegration,
|
|
268
290
|
getPossibleIntegrations,
|
|
269
291
|
} = useCases;
|
|
292
|
+
|
|
293
|
+
// The owner of an integration the caller may reach (404 otherwise), which is
|
|
294
|
+
// what the id-and-owner use cases below expect. `manage: true` is for
|
|
295
|
+
// changing or deleting: an organization's integration needs an admin (403).
|
|
296
|
+
const ownerOf = async (integrationId, user, options) =>
|
|
297
|
+
(await getOwnedIntegrationRecord.execute(integrationId, user, options))
|
|
298
|
+
.userId;
|
|
299
|
+
|
|
270
300
|
router.route('/api/integrations').get(
|
|
271
301
|
catchAsyncError(async (req, res) => {
|
|
272
302
|
const user = await authenticateUser.execute(req);
|
|
273
|
-
const
|
|
274
|
-
const integrations = await getIntegrationsForUser.execute(userId);
|
|
303
|
+
const integrations = await getIntegrationsForUser.execute(user);
|
|
275
304
|
const results = {
|
|
276
305
|
entities: {
|
|
277
|
-
options: await getPossibleIntegrations.execute(
|
|
278
|
-
authorized: await getEntitiesForUser.execute(
|
|
306
|
+
options: await getPossibleIntegrations.execute(),
|
|
307
|
+
authorized: await getEntitiesForUser.execute(user),
|
|
279
308
|
},
|
|
280
309
|
integrations: integrations,
|
|
281
310
|
};
|
|
@@ -287,7 +316,6 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
287
316
|
router.route('/api/integrations').post(
|
|
288
317
|
catchAsyncError(async (req, res) => {
|
|
289
318
|
const user = await authenticateUser.execute(req);
|
|
290
|
-
const userId = user.getId();
|
|
291
319
|
const params = checkRequiredParams(req.body, [
|
|
292
320
|
'entities',
|
|
293
321
|
'config',
|
|
@@ -295,10 +323,17 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
295
323
|
|
|
296
324
|
get(params.config, 'type');
|
|
297
325
|
|
|
326
|
+
const { ownerId, organizationId, adoptUnscoped } =
|
|
327
|
+
await resolveIntegrationOwnership.execute({
|
|
328
|
+
entityIds: params.entities,
|
|
329
|
+
config: params.config,
|
|
330
|
+
user,
|
|
331
|
+
});
|
|
298
332
|
const integration = await createIntegration.execute(
|
|
299
333
|
params.entities,
|
|
300
|
-
|
|
301
|
-
params.config
|
|
334
|
+
ownerId,
|
|
335
|
+
params.config,
|
|
336
|
+
{ organizationId, adoptUnscoped }
|
|
302
337
|
);
|
|
303
338
|
|
|
304
339
|
res.status(201).json(integration);
|
|
@@ -308,12 +343,11 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
308
343
|
router.route('/api/integrations/:integrationId').patch(
|
|
309
344
|
catchAsyncError(async (req, res) => {
|
|
310
345
|
const user = await authenticateUser.execute(req);
|
|
311
|
-
const userId = user.getId();
|
|
312
346
|
const params = checkRequiredParams(req.body, ['config']);
|
|
313
347
|
|
|
314
348
|
const integration = await updateIntegration.execute(
|
|
315
349
|
req.params.integrationId,
|
|
316
|
-
|
|
350
|
+
await ownerOf(req.params.integrationId, user, { manage: true }),
|
|
317
351
|
params.config
|
|
318
352
|
);
|
|
319
353
|
res.json(integration);
|
|
@@ -326,7 +360,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
326
360
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
327
361
|
await deleteIntegrationForUser.execute(
|
|
328
362
|
params.integrationId,
|
|
329
|
-
user
|
|
363
|
+
await ownerOf(params.integrationId, user, { manage: true })
|
|
330
364
|
);
|
|
331
365
|
res.status(204).json({});
|
|
332
366
|
})
|
|
@@ -338,7 +372,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
338
372
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
339
373
|
const integration = await getIntegrationInstance.execute(
|
|
340
374
|
params.integrationId,
|
|
341
|
-
user
|
|
375
|
+
await ownerOf(params.integrationId, user)
|
|
342
376
|
);
|
|
343
377
|
res.json(await integration.send('GET_CONFIG_OPTIONS'));
|
|
344
378
|
})
|
|
@@ -354,7 +388,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
354
388
|
]);
|
|
355
389
|
const integration = await getIntegrationInstance.execute(
|
|
356
390
|
params.integrationId,
|
|
357
|
-
user
|
|
391
|
+
await ownerOf(params.integrationId, user)
|
|
358
392
|
);
|
|
359
393
|
|
|
360
394
|
res.json(
|
|
@@ -368,7 +402,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
368
402
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
369
403
|
const integration = await getIntegrationInstance.execute(
|
|
370
404
|
params.integrationId,
|
|
371
|
-
user
|
|
405
|
+
await ownerOf(params.integrationId, user)
|
|
372
406
|
);
|
|
373
407
|
res.json(await integration.send('GET_USER_ACTIONS', req.body));
|
|
374
408
|
})
|
|
@@ -385,7 +419,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
385
419
|
]);
|
|
386
420
|
const integration = await getIntegrationInstance.execute(
|
|
387
421
|
params.integrationId,
|
|
388
|
-
user
|
|
422
|
+
await ownerOf(params.integrationId, user)
|
|
389
423
|
);
|
|
390
424
|
|
|
391
425
|
res.json(
|
|
@@ -410,7 +444,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
410
444
|
]);
|
|
411
445
|
const integration = await getIntegrationInstance.execute(
|
|
412
446
|
params.integrationId,
|
|
413
|
-
user
|
|
447
|
+
await ownerOf(params.integrationId, user)
|
|
414
448
|
);
|
|
415
449
|
|
|
416
450
|
res.json(
|
|
@@ -431,7 +465,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
431
465
|
]);
|
|
432
466
|
const integration = await getIntegrationInstance.execute(
|
|
433
467
|
params.integrationId,
|
|
434
|
-
user
|
|
468
|
+
await ownerOf(params.integrationId, user)
|
|
435
469
|
);
|
|
436
470
|
res.json(await integration.send(params.actionId, req.body));
|
|
437
471
|
})
|
|
@@ -448,7 +482,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
448
482
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
449
483
|
const integration = await getIntegrationInstance.execute(
|
|
450
484
|
params.integrationId,
|
|
451
|
-
user
|
|
485
|
+
await ownerOf(params.integrationId, user)
|
|
452
486
|
);
|
|
453
487
|
|
|
454
488
|
// We could perhaps augment router with dynamic options? Haven't decided yet, but here may be the place
|
|
@@ -468,7 +502,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
468
502
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
469
503
|
const instance = await getIntegrationInstance.execute(
|
|
470
504
|
params.integrationId,
|
|
471
|
-
user
|
|
505
|
+
await ownerOf(params.integrationId, user)
|
|
472
506
|
);
|
|
473
507
|
|
|
474
508
|
if (!instance) {
|
|
@@ -506,16 +540,21 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
506
540
|
getModule,
|
|
507
541
|
getEntityOptionsById,
|
|
508
542
|
refreshEntityOptions,
|
|
509
|
-
|
|
543
|
+
authorizeEntityForUser,
|
|
544
|
+
createEntityFromCredential,
|
|
510
545
|
} = useCases;
|
|
511
546
|
|
|
512
547
|
router.route('/api/authorize').get(
|
|
513
548
|
catchAsyncError(async (req, res) => {
|
|
514
549
|
const user = await authenticateUser.execute(req);
|
|
515
|
-
const userId = user.getId();
|
|
516
550
|
const params = checkRequiredParams(req.query, ['entityType']);
|
|
551
|
+
// The owner POST stores under, so GET and POST describe one connection.
|
|
552
|
+
const { ownerId } = authorizeEntityForUser.resolveOwnership({
|
|
553
|
+
user,
|
|
554
|
+
entityType: params.entityType,
|
|
555
|
+
});
|
|
517
556
|
const module = await getModuleInstanceFromType.execute(
|
|
518
|
-
|
|
557
|
+
ownerId,
|
|
519
558
|
params.entityType,
|
|
520
559
|
{ state: req.query.state }
|
|
521
560
|
);
|
|
@@ -534,11 +573,15 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
534
573
|
router.route('/api/authorize').post(
|
|
535
574
|
catchAsyncError(async (req, res) => {
|
|
536
575
|
const user = await authenticateUser.execute(req);
|
|
537
|
-
const userId = user.getId();
|
|
538
576
|
const params = checkRequiredParams(req.body, [
|
|
539
577
|
'entityType',
|
|
540
578
|
'data',
|
|
541
579
|
]);
|
|
580
|
+
const ownership = authorizeEntityForUser.resolveOwnership({
|
|
581
|
+
user,
|
|
582
|
+
entityType: params.entityType,
|
|
583
|
+
});
|
|
584
|
+
const userId = ownership.ownerId;
|
|
542
585
|
|
|
543
586
|
const dataKeys =
|
|
544
587
|
params.data && typeof params.data === 'object'
|
|
@@ -550,11 +593,13 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
550
593
|
dataKeys,
|
|
551
594
|
});
|
|
552
595
|
|
|
553
|
-
const entityDetails =
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
596
|
+
const { result: entityDetails } =
|
|
597
|
+
await authorizeEntityForUser.execute({
|
|
598
|
+
user,
|
|
599
|
+
entityType: params.entityType,
|
|
600
|
+
data: params.data,
|
|
601
|
+
ownership,
|
|
602
|
+
});
|
|
558
603
|
|
|
559
604
|
log.info('Entity authorized', {
|
|
560
605
|
eventName: 'frigg.integrations.authorized',
|
|
@@ -571,35 +616,20 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
571
616
|
router.route('/api/entity').post(
|
|
572
617
|
catchAsyncError(async (req, res) => {
|
|
573
618
|
const user = await authenticateUser.execute(req);
|
|
574
|
-
const userId = user.getId();
|
|
575
619
|
const params = checkRequiredParams(req.body, [
|
|
576
620
|
'entityType',
|
|
577
621
|
'data',
|
|
578
622
|
]);
|
|
579
623
|
checkRequiredParams(req.body.data, ['credential_id']);
|
|
580
624
|
|
|
581
|
-
//
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
throw Boom.badRequest('Invalid credential ID');
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
const module = await getModuleInstanceFromType.execute(
|
|
592
|
-
userId,
|
|
593
|
-
params.entityType
|
|
594
|
-
);
|
|
595
|
-
const entityDetails = await module.getEntityDetails(
|
|
596
|
-
module.api,
|
|
597
|
-
null,
|
|
598
|
-
null,
|
|
599
|
-
userId
|
|
625
|
+
// The owner follows the entity type's scope, as /api/authorize.
|
|
626
|
+
res.json(
|
|
627
|
+
await createEntityFromCredential.execute({
|
|
628
|
+
user,
|
|
629
|
+
entityType: params.entityType,
|
|
630
|
+
credentialId: params.data.credential_id,
|
|
631
|
+
})
|
|
600
632
|
);
|
|
601
|
-
|
|
602
|
-
res.json(await module.findOrCreateEntity(entityDetails));
|
|
603
633
|
})
|
|
604
634
|
);
|
|
605
635
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { prisma } = require('../../database/prisma');
|
|
2
|
-
const { MappingAlreadyExistsError } = require('../../errors');
|
|
3
2
|
const {
|
|
4
3
|
toObjectId,
|
|
5
4
|
fromObjectId,
|
|
@@ -181,55 +180,6 @@ class IntegrationMappingRepositoryDocumentDB extends IntegrationMappingRepositor
|
|
|
181
180
|
return this._mapMapping(decryptedMapping);
|
|
182
181
|
}
|
|
183
182
|
|
|
184
|
-
async createMapping(integrationId, sourceId, mapping) {
|
|
185
|
-
const now = new Date();
|
|
186
|
-
const encryptedDocument = await this.encryptionService.encryptFields(
|
|
187
|
-
'IntegrationMapping',
|
|
188
|
-
{
|
|
189
|
-
integrationId,
|
|
190
|
-
sourceId:
|
|
191
|
-
sourceId === null || sourceId === undefined
|
|
192
|
-
? null
|
|
193
|
-
: String(sourceId),
|
|
194
|
-
mapping,
|
|
195
|
-
createdAt: now,
|
|
196
|
-
updatedAt: now,
|
|
197
|
-
}
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
let insertedId;
|
|
201
|
-
try {
|
|
202
|
-
insertedId = await insertOne(
|
|
203
|
-
this.prisma,
|
|
204
|
-
'IntegrationMapping',
|
|
205
|
-
encryptedDocument
|
|
206
|
-
);
|
|
207
|
-
} catch (error) {
|
|
208
|
-
if (error.code === 11000) {
|
|
209
|
-
throw new MappingAlreadyExistsError(integrationId, sourceId, {
|
|
210
|
-
cause: error,
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
throw error;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const created = await findOne(this.prisma, 'IntegrationMapping', {
|
|
217
|
-
_id: insertedId,
|
|
218
|
-
});
|
|
219
|
-
if (!created) {
|
|
220
|
-
throw new Error(
|
|
221
|
-
'Failed to create mapping: Document not found after insert. ' +
|
|
222
|
-
'This indicates a database consistency issue.'
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
return this._mapMapping(
|
|
226
|
-
await this.encryptionService.decryptFields(
|
|
227
|
-
'IntegrationMapping',
|
|
228
|
-
created
|
|
229
|
-
)
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
183
|
async findMappingsByIntegration(integrationId) {
|
|
234
184
|
const filter = {};
|
|
235
185
|
if (integrationId) filter.integrationId = integrationId;
|
|
@@ -39,21 +39,6 @@ class IntegrationMappingRepositoryInterface {
|
|
|
39
39
|
throw new Error('Method upsertMapping must be implemented by subclass');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
/**
|
|
43
|
-
* Insert a mapping, failing if one already exists for the
|
|
44
|
-
* (integrationId, sourceId) pair. Atomic: usable as a claim/lock row.
|
|
45
|
-
*
|
|
46
|
-
* @param {string|number} integrationId - The integration ID
|
|
47
|
-
* @param {string} sourceId - The source ID for lookup
|
|
48
|
-
* @param {Object} mapping - The mapping data
|
|
49
|
-
* @returns {Promise<Object>} The created mapping document
|
|
50
|
-
* @throws {MappingAlreadyExistsError} If the pair already exists
|
|
51
|
-
* @abstract
|
|
52
|
-
*/
|
|
53
|
-
async createMapping(integrationId, sourceId, mapping) {
|
|
54
|
-
throw new Error('createMapping must be implemented by subclass');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
42
|
/**
|
|
58
43
|
* Find all mappings for an integration
|
|
59
44
|
*
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { prisma } = require('../../database/prisma');
|
|
2
|
-
const { MappingAlreadyExistsError } = require('../../errors');
|
|
3
2
|
const {
|
|
4
3
|
assertMappingWrittenUnencrypted,
|
|
5
4
|
decryptQueriedMappings,
|
|
@@ -94,34 +93,6 @@ class IntegrationMappingRepositoryMongo extends IntegrationMappingRepositoryInte
|
|
|
94
93
|
});
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
/**
|
|
98
|
-
* Insert a mapping; fails if (integrationId, sourceId) already exists
|
|
99
|
-
*
|
|
100
|
-
* @param {string} integrationId - The integration ID
|
|
101
|
-
* @param {string} sourceId - The source ID
|
|
102
|
-
* @param {Object} mapping - The mapping data
|
|
103
|
-
* @returns {Promise<Object>} The created mapping document
|
|
104
|
-
* @throws {MappingAlreadyExistsError} If the pair already exists
|
|
105
|
-
*/
|
|
106
|
-
async createMapping(integrationId, sourceId, mapping) {
|
|
107
|
-
try {
|
|
108
|
-
return await this.prisma.integrationMapping.create({
|
|
109
|
-
data: {
|
|
110
|
-
integrationId,
|
|
111
|
-
sourceId: this._toString(sourceId),
|
|
112
|
-
mapping,
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
} catch (error) {
|
|
116
|
-
if (error.code === 'P2002') {
|
|
117
|
-
throw new MappingAlreadyExistsError(integrationId, sourceId, {
|
|
118
|
-
cause: error,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
throw error;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
96
|
/**
|
|
126
97
|
* Find all mappings for an integration
|
|
127
98
|
* Replaces: IntegrationMapping.find({ integration: integrationId })
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { prisma } = require('../../database/prisma');
|
|
2
|
-
const { MappingAlreadyExistsError } = require('../../errors');
|
|
3
2
|
const {
|
|
4
3
|
assertMappingWrittenUnencrypted,
|
|
5
4
|
decryptQueriedMappings,
|
|
@@ -151,35 +150,6 @@ class IntegrationMappingRepositoryPostgres extends IntegrationMappingRepositoryI
|
|
|
151
150
|
return this._convertMappingIds(result);
|
|
152
151
|
}
|
|
153
152
|
|
|
154
|
-
/**
|
|
155
|
-
* Insert a mapping; fails if (integrationId, sourceId) already exists
|
|
156
|
-
*
|
|
157
|
-
* @param {string} integrationId - The integration ID
|
|
158
|
-
* @param {string} sourceId - The source ID
|
|
159
|
-
* @param {Object} mapping - The mapping data
|
|
160
|
-
* @returns {Promise<Object>} The created mapping document
|
|
161
|
-
* @throws {MappingAlreadyExistsError} If the pair already exists
|
|
162
|
-
*/
|
|
163
|
-
async createMapping(integrationId, sourceId, mapping) {
|
|
164
|
-
try {
|
|
165
|
-
const created = await this.prisma.integrationMapping.create({
|
|
166
|
-
data: {
|
|
167
|
-
integrationId: this._stringToInt(integrationId),
|
|
168
|
-
sourceId: this._toString(sourceId),
|
|
169
|
-
mapping,
|
|
170
|
-
},
|
|
171
|
-
});
|
|
172
|
-
return this._convertMappingIds(created);
|
|
173
|
-
} catch (error) {
|
|
174
|
-
if (error.code === 'P2002') {
|
|
175
|
-
throw new MappingAlreadyExistsError(integrationId, sourceId, {
|
|
176
|
-
cause: error,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
throw error;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
153
|
/**
|
|
184
154
|
* Find all mappings for an integration
|
|
185
155
|
* Replaces: IntegrationMapping.find({ integration: integrationId })
|