@friggframework/core 2.0.0--canary.686.3e27a92.0 → 2.0.0--canary.663.8de669c.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/CLAUDE.md +0 -28
- package/README.md +0 -105
- package/application/commands/integration-commands.js +10 -20
- package/application/commands/scheduler-commands.js +7 -11
- package/application/commands/user-commands.js +5 -17
- package/application/index.js +2 -6
- package/core/Worker.js +7 -31
- package/core/create-handler.js +0 -9
- package/credential/repositories/credential-repository-documentdb.js +0 -34
- package/credential/repositories/credential-repository-interface.js +0 -15
- package/credential/repositories/credential-repository-mongo.js +0 -23
- package/credential/repositories/credential-repository-postgres.js +0 -28
- package/database/config.js +24 -48
- package/database/documentdb-utils.js +1 -6
- package/database/encryption/encryption-config.js +31 -10
- package/database/encryption/encryption-schema-registry.js +12 -93
- package/database/prisma.js +2 -4
- package/generated/prisma-mongodb/edge.js +4 -43
- package/generated/prisma-mongodb/index-browser.js +1 -40
- package/generated/prisma-mongodb/index.d.ts +111 -4739
- package/generated/prisma-mongodb/index.js +4 -43
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +0 -92
- package/generated/prisma-mongodb/wasm.js +4 -43
- package/generated/prisma-postgresql/edge.js +4 -43
- package/generated/prisma-postgresql/index-browser.js +1 -40
- package/generated/prisma-postgresql/index.d.ts +33 -4966
- package/generated/prisma-postgresql/index.js +4 -43
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +0 -87
- package/generated/prisma-postgresql/wasm.js +4 -43
- package/handlers/app-definition-loader.js +19 -121
- package/handlers/app-handler-helpers.js +3 -25
- package/handlers/backend-utils.js +25 -31
- package/handlers/middleware/admin-auth.js +1 -14
- package/handlers/routers/auth.js +10 -46
- package/handlers/routers/health.js +4 -13
- package/handlers/routers/integration-defined-routers.js +92 -144
- package/handlers/routers/integration-webhook-routers.js +64 -102
- package/handlers/workers/integration-defined-workers.js +2 -5
- package/index.js +1 -65
- package/infrastructure/scheduler/index.js +6 -19
- package/infrastructure/scheduler/scheduler-service-factory.js +7 -55
- package/integrations/index.js +0 -1
- package/integrations/integration-router.js +96 -131
- package/integrations/repositories/integration-repository-documentdb.js +3 -35
- package/integrations/repositories/integration-repository-interface.js +1 -17
- package/integrations/repositories/integration-repository-mongo.js +76 -59
- package/integrations/repositories/integration-repository-postgres.js +76 -62
- package/integrations/tests/doubles/test-integration-repository.js +1 -12
- package/integrations/use-cases/create-integration.js +20 -55
- package/integrations/use-cases/get-integrations-for-user.js +40 -80
- package/integrations/use-cases/index.js +1 -7
- package/integrations/utils/map-integration-dto.js +14 -43
- package/modules/index.js +0 -14
- package/modules/module-factory.js +0 -12
- package/modules/module.js +2 -53
- package/modules/repositories/module-repository-documentdb.js +6 -51
- package/modules/repositories/module-repository-interface.js +2 -19
- package/modules/repositories/module-repository-mongo.js +74 -67
- package/modules/repositories/module-repository-postgres.js +74 -66
- package/modules/repositories/module-repository.js +1 -2
- package/modules/requester/requester.js +2 -27
- package/modules/use-cases/get-entities-for-user.js +13 -26
- package/modules/use-cases/get-entity-options-by-id.js +4 -10
- 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 +4 -10
- package/modules/use-cases/process-authorization-callback.js +19 -53
- package/modules/use-cases/refresh-entity-options.js +4 -10
- package/modules/use-cases/test-module-auth.js +4 -10
- package/package.json +5 -6
- package/prisma-mongodb/schema.prisma +0 -92
- package/prisma-postgresql/schema.prisma +0 -87
- package/queues/index.js +0 -25
- package/types/index.d.ts +0 -2
- package/user/repositories/user-repository-documentdb.js +2 -27
- package/user/repositories/user-repository-interface.js +0 -18
- package/user/repositories/user-repository-mongo.js +0 -24
- package/user/repositories/user-repository-postgres.js +0 -18
- package/user/use-cases/authenticate-user.js +1 -7
- package/user/use-cases/get-user-from-adopter-jwt.js +124 -95
- package/user/use-cases/get-user-from-x-frigg-headers.js +80 -83
- package/user/user.js +1 -64
- package/credential/use-cases/credential-operations-for-user.js +0 -202
- package/credential/use-cases/reauthorize-credential-for-user.js +0 -73
- package/database/organization-where.js +0 -18
- package/database/unique-violation.js +0 -25
- package/extensions/bootstrap-runner.js +0 -43
- package/extensions/extension-loader.js +0 -187
- package/extensions/index.js +0 -41
- package/extensions/initialize-app.js +0 -123
- package/extensions/route-mounter.js +0 -103
- package/extensions/schema-composer.js +0 -188
- package/infrastructure/scheduler/netlify-scheduler-adapter.js +0 -216
- package/infrastructure/scheduler/scheduled-job-repository.js +0 -118
- package/integrations/repositories/integration-not-found.js +0 -14
- package/integrations/schedule-config.js +0 -80
- package/integrations/use-cases/dispatch-ongoing-syncs.js +0 -100
- package/integrations/use-cases/integration-operations-for-user.js +0 -256
- package/integrations/use-cases/resolve-integration-ownership.js +0 -177
- package/management-api/create-management-api-router.js +0 -49
- package/management-api/error-response.js +0 -116
- package/management-api/management-api-config.js +0 -151
- package/management-api/meta-router.js +0 -76
- package/management-api/openapi/build-openapi.js +0 -144
- package/management-api/openapi/components.js +0 -408
- package/management-api/openapi/v1-operations.js +0 -83
- package/management-api/openapi/v2-operations.js +0 -264
- package/management-api/route-registry.js +0 -411
- package/management-api/test-support/http-client.js +0 -39
- package/management-api/use-cases/get-management-api-meta.js +0 -57
- package/management-api/v1-deprecation.js +0 -120
- package/management-api/v2/create-v2-router.js +0 -85
- package/management-api/v2/dependencies.js +0 -281
- package/management-api/v2/dto.js +0 -143
- package/management-api/v2/handlers/authorization.js +0 -94
- package/management-api/v2/handlers/credentials.js +0 -33
- package/management-api/v2/handlers/entities.js +0 -77
- package/management-api/v2/handlers/integrations.js +0 -128
- package/management-api/v2/handlers/proxy.js +0 -34
- package/management-api/v2/request.js +0 -85
- package/management-api/v2/test-support/fake-dependencies.js +0 -103
- package/modules/domain/authorization-session.js +0 -144
- package/modules/entity-scope.js +0 -15
- package/modules/entity-type-registry.js +0 -311
- package/modules/proxy/proxy-errors.js +0 -20
- package/modules/proxy/proxy-path.js +0 -179
- package/modules/proxy/proxy-policy.js +0 -248
- package/modules/repositories/authorization-session-repository-documentdb.js +0 -112
- package/modules/repositories/authorization-session-repository-factory.js +0 -31
- package/modules/repositories/authorization-session-repository-interface.js +0 -47
- package/modules/repositories/authorization-session-repository-prisma.js +0 -87
- package/modules/repositories/entity-not-found.js +0 -18
- package/modules/requester/proxy-request.js +0 -244
- package/modules/scope-config.js +0 -192
- package/modules/scope-policy.js +0 -112
- package/modules/scope-resolution.js +0 -288
- package/modules/scope-visibility.js +0 -247
- package/modules/tests/doubles/in-memory-authorization-session-repository.js +0 -45
- package/modules/tests/doubles/ownership-matching.js +0 -18
- package/modules/use-cases/authorize-entity-for-user.js +0 -61
- package/modules/use-cases/create-entity-from-credential.js +0 -113
- package/modules/use-cases/entity-operations-for-user.js +0 -162
- package/modules/use-cases/entity-types.js +0 -139
- package/modules/use-cases/execute-entity-proxy-request.js +0 -286
- package/modules/use-cases/get-authorization-requirements.js +0 -100
- package/modules/use-cases/get-entity-module-for-user.js +0 -113
- package/modules/use-cases/manage-access.js +0 -21
- package/modules/use-cases/multi-step-authorization.js +0 -329
- package/prisma-postgresql/migrations/20261003000000_add_authorization_session/migration.sql +0 -28
- package/prisma-postgresql/migrations/20261015000000_add_organization_membership/migration.sql +0 -26
- package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +0 -25
- package/prisma-postgresql/migrations/20261017000000_add_scheduled_job/migration.sql +0 -28
- package/providers/index.js +0 -23
- package/providers/resolve-provider.js +0 -93
- package/providers/runtime-detection.js +0 -124
- package/queues/providers/index.js +0 -11
- package/queues/providers/netlify-background-provider.js +0 -150
- package/queues/providers/qstash-queue-provider.js +0 -219
- package/queues/providers/sqs-queue-provider.js +0 -70
- package/queues/queue-client-interface.js +0 -55
- package/queues/queue-message-auth.js +0 -193
- package/queues/queue-provider-factory.js +0 -101
- package/queues/queue-provider.js +0 -65
- package/queues/sqs-queue-client.js +0 -81
- package/types/modules/index.d.ts +0 -197
- package/types/user/index.d.ts +0 -134
- package/user/adopter-jwt-config.js +0 -177
- package/user/adopter-jwt-errors.js +0 -59
- package/user/adopter-token-verifier.js +0 -122
- package/user/app-user-helpers.js +0 -97
- package/user/create-user-authentication.js +0 -64
- package/user/membership.js +0 -51
- package/user/repositories/organization-membership-record.js +0 -19
- package/user/repositories/organization-membership-repository-documentdb.js +0 -106
- package/user/repositories/organization-membership-repository-factory.js +0 -42
- package/user/repositories/organization-membership-repository-interface.js +0 -57
- package/user/repositories/organization-membership-repository-mongo.js +0 -13
- package/user/repositories/organization-membership-repository-postgres.js +0 -29
- package/user/repositories/organization-membership-repository-prisma.js +0 -81
- package/user/tests/doubles/adopter-jwt-fixtures.js +0 -220
- package/user/use-cases/ensure-organization-membership.js +0 -92
- package/user/use-cases/find-individual-users-by-organization.js +0 -54
|
@@ -31,6 +31,9 @@ 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');
|
|
34
37
|
const {
|
|
35
38
|
GetModuleInstanceFromType,
|
|
36
39
|
} = require('../modules/use-cases/get-module-instance-from-type');
|
|
@@ -51,51 +54,47 @@ const {
|
|
|
51
54
|
const {
|
|
52
55
|
createUserRepository,
|
|
53
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');
|
|
54
66
|
const {
|
|
55
67
|
AuthenticateWithSharedSecret,
|
|
56
68
|
} = require('../user/use-cases/authenticate-with-shared-secret');
|
|
57
69
|
const { AuthenticateUser } = require('../user/use-cases/authenticate-user');
|
|
58
|
-
const {
|
|
59
|
-
buildUserAuthentication,
|
|
60
|
-
} = require('../user/create-user-authentication');
|
|
61
70
|
const {
|
|
62
71
|
ProcessAuthorizationCallback,
|
|
63
72
|
} = 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');
|
|
75
73
|
|
|
76
74
|
const log = getLogger('frigg.integrations');
|
|
77
75
|
|
|
78
76
|
function createIntegrationRouter() {
|
|
79
|
-
|
|
80
|
-
|
|
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 });
|
|
77
|
+
const { integrations: integrationClasses, userConfig } =
|
|
78
|
+
loadAppDefinition();
|
|
90
79
|
const moduleRepository = createModuleRepository();
|
|
91
80
|
const integrationRepository = createIntegrationRepository();
|
|
92
81
|
const credentialRepository = createCredentialRepository();
|
|
93
82
|
const userRepository = createUserRepository();
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
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
|
+
});
|
|
99
98
|
|
|
100
99
|
const authenticateWithSharedSecret = new AuthenticateWithSharedSecret();
|
|
101
100
|
|
|
@@ -109,7 +108,8 @@ function createIntegrationRouter() {
|
|
|
109
108
|
|
|
110
109
|
const moduleFactory = new ModuleFactory({
|
|
111
110
|
moduleRepository,
|
|
112
|
-
moduleDefinitions
|
|
111
|
+
moduleDefinitions:
|
|
112
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
113
113
|
});
|
|
114
114
|
const deleteIntegrationForUser = new DeleteIntegrationForUser({
|
|
115
115
|
integrationRepository,
|
|
@@ -122,19 +122,6 @@ 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,
|
|
138
125
|
});
|
|
139
126
|
|
|
140
127
|
const getCredentialForUser = new GetCredentialForUser({
|
|
@@ -149,8 +136,8 @@ function createIntegrationRouter() {
|
|
|
149
136
|
|
|
150
137
|
const getEntitiesForUser = new GetEntitiesForUser({
|
|
151
138
|
moduleRepository,
|
|
152
|
-
moduleDefinitions
|
|
153
|
-
|
|
139
|
+
moduleDefinitions:
|
|
140
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
154
141
|
});
|
|
155
142
|
|
|
156
143
|
const getIntegrationInstance = new GetIntegrationInstance({
|
|
@@ -166,65 +153,54 @@ function createIntegrationRouter() {
|
|
|
166
153
|
});
|
|
167
154
|
|
|
168
155
|
const getModuleInstanceFromType = new GetModuleInstanceFromType({
|
|
169
|
-
moduleDefinitions
|
|
156
|
+
moduleDefinitions:
|
|
157
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
170
158
|
});
|
|
171
159
|
|
|
172
160
|
const getEntityOptionsByType = new GetEntityOptionsByType({
|
|
173
|
-
moduleDefinitions
|
|
161
|
+
moduleDefinitions:
|
|
162
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
174
163
|
});
|
|
175
164
|
|
|
176
165
|
const testModuleAuth = new TestModuleAuth({
|
|
177
166
|
moduleRepository,
|
|
178
|
-
moduleDefinitions
|
|
179
|
-
|
|
167
|
+
moduleDefinitions:
|
|
168
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
180
169
|
});
|
|
181
170
|
|
|
182
171
|
const getModule = new GetModule({
|
|
183
172
|
moduleRepository,
|
|
184
|
-
moduleDefinitions
|
|
185
|
-
|
|
173
|
+
moduleDefinitions:
|
|
174
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
186
175
|
});
|
|
187
176
|
|
|
188
177
|
const getEntityOptionsById = new GetEntityOptionsById({
|
|
189
178
|
moduleRepository,
|
|
190
|
-
moduleDefinitions
|
|
191
|
-
|
|
179
|
+
moduleDefinitions:
|
|
180
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
192
181
|
});
|
|
193
182
|
|
|
194
183
|
const refreshEntityOptions = new RefreshEntityOptions({
|
|
195
184
|
moduleRepository,
|
|
196
|
-
moduleDefinitions
|
|
197
|
-
|
|
185
|
+
moduleDefinitions:
|
|
186
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
198
187
|
});
|
|
199
188
|
|
|
200
189
|
const getPossibleIntegrations = new GetPossibleIntegrations({
|
|
201
190
|
integrationClasses,
|
|
202
191
|
});
|
|
203
192
|
|
|
204
|
-
// The owner of what an authorization creates follows its scope (ADR-056 §3.2).
|
|
205
193
|
const processAuthorizationCallback = new ProcessAuthorizationCallback({
|
|
206
194
|
moduleRepository,
|
|
207
195
|
credentialRepository,
|
|
208
196
|
integrationRepository,
|
|
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,
|
|
197
|
+
moduleDefinitions:
|
|
198
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
221
199
|
});
|
|
222
200
|
|
|
223
201
|
const router = express();
|
|
224
202
|
|
|
225
203
|
setIntegrationRoutes(router, authenticateUser, {
|
|
226
|
-
resolveIntegrationOwnership,
|
|
227
|
-
getOwnedIntegrationRecord,
|
|
228
204
|
createIntegration,
|
|
229
205
|
deleteIntegrationForUser,
|
|
230
206
|
getIntegrationsForUser,
|
|
@@ -241,8 +217,7 @@ function createIntegrationRouter() {
|
|
|
241
217
|
getModule,
|
|
242
218
|
getEntityOptionsById,
|
|
243
219
|
refreshEntityOptions,
|
|
244
|
-
|
|
245
|
-
createEntityFromCredential,
|
|
220
|
+
processAuthorizationCallback,
|
|
246
221
|
});
|
|
247
222
|
return router;
|
|
248
223
|
}
|
|
@@ -279,8 +254,6 @@ function checkRequiredParams(params, requiredKeys) {
|
|
|
279
254
|
*/
|
|
280
255
|
function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
281
256
|
const {
|
|
282
|
-
resolveIntegrationOwnership,
|
|
283
|
-
getOwnedIntegrationRecord,
|
|
284
257
|
createIntegration,
|
|
285
258
|
deleteIntegrationForUser,
|
|
286
259
|
getIntegrationsForUser,
|
|
@@ -289,22 +262,15 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
289
262
|
updateIntegration,
|
|
290
263
|
getPossibleIntegrations,
|
|
291
264
|
} = 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
|
-
|
|
300
265
|
router.route('/api/integrations').get(
|
|
301
266
|
catchAsyncError(async (req, res) => {
|
|
302
267
|
const user = await authenticateUser.execute(req);
|
|
303
|
-
const
|
|
268
|
+
const userId = user.getId();
|
|
269
|
+
const integrations = await getIntegrationsForUser.execute(userId);
|
|
304
270
|
const results = {
|
|
305
271
|
entities: {
|
|
306
272
|
options: await getPossibleIntegrations.execute(),
|
|
307
|
-
authorized: await getEntitiesForUser.execute(
|
|
273
|
+
authorized: await getEntitiesForUser.execute(userId),
|
|
308
274
|
},
|
|
309
275
|
integrations: integrations,
|
|
310
276
|
};
|
|
@@ -316,6 +282,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
316
282
|
router.route('/api/integrations').post(
|
|
317
283
|
catchAsyncError(async (req, res) => {
|
|
318
284
|
const user = await authenticateUser.execute(req);
|
|
285
|
+
const userId = user.getId();
|
|
319
286
|
const params = checkRequiredParams(req.body, [
|
|
320
287
|
'entities',
|
|
321
288
|
'config',
|
|
@@ -323,17 +290,10 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
323
290
|
|
|
324
291
|
get(params.config, 'type');
|
|
325
292
|
|
|
326
|
-
const { ownerId, organizationId, adoptUnscoped } =
|
|
327
|
-
await resolveIntegrationOwnership.execute({
|
|
328
|
-
entityIds: params.entities,
|
|
329
|
-
config: params.config,
|
|
330
|
-
user,
|
|
331
|
-
});
|
|
332
293
|
const integration = await createIntegration.execute(
|
|
333
294
|
params.entities,
|
|
334
|
-
|
|
335
|
-
params.config
|
|
336
|
-
{ organizationId, adoptUnscoped }
|
|
295
|
+
userId,
|
|
296
|
+
params.config
|
|
337
297
|
);
|
|
338
298
|
|
|
339
299
|
res.status(201).json(integration);
|
|
@@ -343,11 +303,12 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
343
303
|
router.route('/api/integrations/:integrationId').patch(
|
|
344
304
|
catchAsyncError(async (req, res) => {
|
|
345
305
|
const user = await authenticateUser.execute(req);
|
|
306
|
+
const userId = user.getId();
|
|
346
307
|
const params = checkRequiredParams(req.body, ['config']);
|
|
347
308
|
|
|
348
309
|
const integration = await updateIntegration.execute(
|
|
349
310
|
req.params.integrationId,
|
|
350
|
-
|
|
311
|
+
userId,
|
|
351
312
|
params.config
|
|
352
313
|
);
|
|
353
314
|
res.json(integration);
|
|
@@ -360,7 +321,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
360
321
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
361
322
|
await deleteIntegrationForUser.execute(
|
|
362
323
|
params.integrationId,
|
|
363
|
-
|
|
324
|
+
user.getId()
|
|
364
325
|
);
|
|
365
326
|
res.status(204).json({});
|
|
366
327
|
})
|
|
@@ -372,7 +333,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
372
333
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
373
334
|
const integration = await getIntegrationInstance.execute(
|
|
374
335
|
params.integrationId,
|
|
375
|
-
|
|
336
|
+
user.getId()
|
|
376
337
|
);
|
|
377
338
|
res.json(await integration.send('GET_CONFIG_OPTIONS'));
|
|
378
339
|
})
|
|
@@ -388,7 +349,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
388
349
|
]);
|
|
389
350
|
const integration = await getIntegrationInstance.execute(
|
|
390
351
|
params.integrationId,
|
|
391
|
-
|
|
352
|
+
user.getId()
|
|
392
353
|
);
|
|
393
354
|
|
|
394
355
|
res.json(
|
|
@@ -402,7 +363,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
402
363
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
403
364
|
const integration = await getIntegrationInstance.execute(
|
|
404
365
|
params.integrationId,
|
|
405
|
-
|
|
366
|
+
user.getId()
|
|
406
367
|
);
|
|
407
368
|
res.json(await integration.send('GET_USER_ACTIONS', req.body));
|
|
408
369
|
})
|
|
@@ -419,7 +380,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
419
380
|
]);
|
|
420
381
|
const integration = await getIntegrationInstance.execute(
|
|
421
382
|
params.integrationId,
|
|
422
|
-
|
|
383
|
+
user.getId()
|
|
423
384
|
);
|
|
424
385
|
|
|
425
386
|
res.json(
|
|
@@ -444,7 +405,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
444
405
|
]);
|
|
445
406
|
const integration = await getIntegrationInstance.execute(
|
|
446
407
|
params.integrationId,
|
|
447
|
-
|
|
408
|
+
user.getId()
|
|
448
409
|
);
|
|
449
410
|
|
|
450
411
|
res.json(
|
|
@@ -465,7 +426,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
465
426
|
]);
|
|
466
427
|
const integration = await getIntegrationInstance.execute(
|
|
467
428
|
params.integrationId,
|
|
468
|
-
|
|
429
|
+
user.getId()
|
|
469
430
|
);
|
|
470
431
|
res.json(await integration.send(params.actionId, req.body));
|
|
471
432
|
})
|
|
@@ -482,7 +443,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
482
443
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
483
444
|
const integration = await getIntegrationInstance.execute(
|
|
484
445
|
params.integrationId,
|
|
485
|
-
|
|
446
|
+
user.getId()
|
|
486
447
|
);
|
|
487
448
|
|
|
488
449
|
// We could perhaps augment router with dynamic options? Haven't decided yet, but here may be the place
|
|
@@ -502,7 +463,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
502
463
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
503
464
|
const instance = await getIntegrationInstance.execute(
|
|
504
465
|
params.integrationId,
|
|
505
|
-
|
|
466
|
+
user.getId()
|
|
506
467
|
);
|
|
507
468
|
|
|
508
469
|
if (!instance) {
|
|
@@ -540,21 +501,16 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
540
501
|
getModule,
|
|
541
502
|
getEntityOptionsById,
|
|
542
503
|
refreshEntityOptions,
|
|
543
|
-
|
|
544
|
-
createEntityFromCredential,
|
|
504
|
+
processAuthorizationCallback,
|
|
545
505
|
} = useCases;
|
|
546
506
|
|
|
547
507
|
router.route('/api/authorize').get(
|
|
548
508
|
catchAsyncError(async (req, res) => {
|
|
549
509
|
const user = await authenticateUser.execute(req);
|
|
510
|
+
const userId = user.getId();
|
|
550
511
|
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
|
-
});
|
|
556
512
|
const module = await getModuleInstanceFromType.execute(
|
|
557
|
-
|
|
513
|
+
userId,
|
|
558
514
|
params.entityType,
|
|
559
515
|
{ state: req.query.state }
|
|
560
516
|
);
|
|
@@ -573,15 +529,11 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
573
529
|
router.route('/api/authorize').post(
|
|
574
530
|
catchAsyncError(async (req, res) => {
|
|
575
531
|
const user = await authenticateUser.execute(req);
|
|
532
|
+
const userId = user.getId();
|
|
576
533
|
const params = checkRequiredParams(req.body, [
|
|
577
534
|
'entityType',
|
|
578
535
|
'data',
|
|
579
536
|
]);
|
|
580
|
-
const ownership = authorizeEntityForUser.resolveOwnership({
|
|
581
|
-
user,
|
|
582
|
-
entityType: params.entityType,
|
|
583
|
-
});
|
|
584
|
-
const userId = ownership.ownerId;
|
|
585
537
|
|
|
586
538
|
const dataKeys =
|
|
587
539
|
params.data && typeof params.data === 'object'
|
|
@@ -593,13 +545,11 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
593
545
|
dataKeys,
|
|
594
546
|
});
|
|
595
547
|
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
ownership,
|
|
602
|
-
});
|
|
548
|
+
const entityDetails = await processAuthorizationCallback.execute(
|
|
549
|
+
userId,
|
|
550
|
+
params.entityType,
|
|
551
|
+
params.data
|
|
552
|
+
);
|
|
603
553
|
|
|
604
554
|
log.info('Entity authorized', {
|
|
605
555
|
eventName: 'frigg.integrations.authorized',
|
|
@@ -616,20 +566,35 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
616
566
|
router.route('/api/entity').post(
|
|
617
567
|
catchAsyncError(async (req, res) => {
|
|
618
568
|
const user = await authenticateUser.execute(req);
|
|
569
|
+
const userId = user.getId();
|
|
619
570
|
const params = checkRequiredParams(req.body, [
|
|
620
571
|
'entityType',
|
|
621
572
|
'data',
|
|
622
573
|
]);
|
|
623
574
|
checkRequiredParams(req.body.data, ['credential_id']);
|
|
624
575
|
|
|
625
|
-
//
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
entityType: params.entityType,
|
|
630
|
-
credentialId: params.data.credential_id,
|
|
631
|
-
})
|
|
576
|
+
// May want to pass along the user ID as well so credential ID's can't be fished???
|
|
577
|
+
const credential = await getCredentialForUser.execute(
|
|
578
|
+
params.data.credential_id,
|
|
579
|
+
userId
|
|
632
580
|
);
|
|
581
|
+
|
|
582
|
+
if (!credential) {
|
|
583
|
+
throw Boom.badRequest('Invalid credential ID');
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const module = await getModuleInstanceFromType.execute(
|
|
587
|
+
userId,
|
|
588
|
+
params.entityType
|
|
589
|
+
);
|
|
590
|
+
const entityDetails = await module.getEntityDetails(
|
|
591
|
+
module.api,
|
|
592
|
+
null,
|
|
593
|
+
null,
|
|
594
|
+
userId
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
res.json(await module.findOrCreateEntity(entityDetails));
|
|
633
598
|
})
|
|
634
599
|
);
|
|
635
600
|
|
|
@@ -14,7 +14,6 @@ const {
|
|
|
14
14
|
IntegrationRepositoryInterface,
|
|
15
15
|
} = require('./integration-repository-interface');
|
|
16
16
|
const { validateConfigPatch } = require('./config-patch-shared');
|
|
17
|
-
const { integrationNotFoundError } = require('./integration-not-found');
|
|
18
17
|
|
|
19
18
|
class IntegrationRepositoryDocumentDB extends IntegrationRepositoryInterface {
|
|
20
19
|
constructor() {
|
|
@@ -29,28 +28,6 @@ class IntegrationRepositoryDocumentDB extends IntegrationRepositoryInterface {
|
|
|
29
28
|
return records.map((doc) => this._mapIntegration(doc));
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
/**
|
|
33
|
-
* Find integrations matching any of the owner/organization pairs, in one
|
|
34
|
-
* query. `organizationId: null` matches rows with no organization (a raw
|
|
35
|
-
* MongoDB `null` also matches a missing field). The caller (a use case)
|
|
36
|
-
* decides which pairs; this only runs them.
|
|
37
|
-
*
|
|
38
|
-
* @param {Array<{userId: string, organizationId: (string|null)}>} clauses
|
|
39
|
-
* @returns {Promise<Array>}
|
|
40
|
-
*/
|
|
41
|
-
async findIntegrationsByOwnership(clauses) {
|
|
42
|
-
if (!Array.isArray(clauses) || clauses.length === 0) return [];
|
|
43
|
-
// Drained: a list can hold more than the first cursor batch (~101).
|
|
44
|
-
const records = await findManyDrained(this.prisma, 'Integration', {
|
|
45
|
-
$or: clauses.map(({ userId, organizationId }) => ({
|
|
46
|
-
userId: toObjectId(userId),
|
|
47
|
-
organizationId:
|
|
48
|
-
organizationId === null ? null : toObjectId(organizationId),
|
|
49
|
-
})),
|
|
50
|
-
});
|
|
51
|
-
return records.map((doc) => this._mapIntegration(doc));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
31
|
async findIntegrations({ type, status } = {}) {
|
|
55
32
|
const filter = {};
|
|
56
33
|
if (type) {
|
|
@@ -91,11 +68,11 @@ class IntegrationRepositoryDocumentDB extends IntegrationRepositoryInterface {
|
|
|
91
68
|
async findIntegrationById(id) {
|
|
92
69
|
const objectId = toObjectId(id);
|
|
93
70
|
if (!objectId) {
|
|
94
|
-
throw
|
|
71
|
+
throw new Error(`Integration with id ${id} not found`);
|
|
95
72
|
}
|
|
96
73
|
const doc = await findOne(this.prisma, 'Integration', { _id: objectId });
|
|
97
74
|
if (!doc) {
|
|
98
|
-
throw
|
|
75
|
+
throw new Error(`Integration with id ${id} not found`);
|
|
99
76
|
}
|
|
100
77
|
return this._mapIntegration(doc);
|
|
101
78
|
}
|
|
@@ -155,18 +132,10 @@ class IntegrationRepositoryDocumentDB extends IntegrationRepositoryInterface {
|
|
|
155
132
|
return true;
|
|
156
133
|
}
|
|
157
134
|
|
|
158
|
-
|
|
159
|
-
* @param {Array<string>} entities - entity ids
|
|
160
|
-
* @param {string} userId - owner (the person, or the organization's user)
|
|
161
|
-
* @param {Object} config - Integration configuration
|
|
162
|
-
* @param {{organizationId?: (string|null)}} [tenancy] - the organization the
|
|
163
|
-
* integration is created in (ADR-056 §3.6)
|
|
164
|
-
*/
|
|
165
|
-
async createIntegration(entities, userId, config, tenancy = {}) {
|
|
135
|
+
async createIntegration(entities, userId, config) {
|
|
166
136
|
const now = new Date();
|
|
167
137
|
const document = {
|
|
168
138
|
userId: toObjectId(userId) || null,
|
|
169
|
-
organizationId: toObjectId(tenancy.organizationId) || null,
|
|
170
139
|
config,
|
|
171
140
|
version: '0.0.0',
|
|
172
141
|
status: 'IN_CREATION',
|
|
@@ -329,7 +298,6 @@ class IntegrationRepositoryDocumentDB extends IntegrationRepositoryInterface {
|
|
|
329
298
|
id: fromObjectId(doc?._id),
|
|
330
299
|
entitiesIds: (doc?.entityIds || []).map((value) => fromObjectId(value)),
|
|
331
300
|
userId: fromObjectId(doc?.userId),
|
|
332
|
-
organizationId: fromObjectId(doc?.organizationId) ?? null,
|
|
333
301
|
config: doc?.config ?? null,
|
|
334
302
|
version: doc?.version ?? null,
|
|
335
303
|
status: doc?.status ?? null,
|
|
@@ -10,20 +10,6 @@
|
|
|
10
10
|
* @abstract
|
|
11
11
|
*/
|
|
12
12
|
class IntegrationRepositoryInterface {
|
|
13
|
-
/**
|
|
14
|
-
* Find integrations matching any of the owner/organization pairs, in one
|
|
15
|
-
* query (ADR-056 §3.6). `organizationId: null` matches rows with no
|
|
16
|
-
* organization. Which pairs is decided by the caller
|
|
17
|
-
* (modules/entity-scope.js), not here.
|
|
18
|
-
*
|
|
19
|
-
* @param {Array<{userId: string|number, organizationId: (string|number|null)}>} clauses
|
|
20
|
-
* @returns {Promise<Array>} Array of integration objects
|
|
21
|
-
* @abstract
|
|
22
|
-
*/
|
|
23
|
-
async findIntegrationsByOwnership(clauses) {
|
|
24
|
-
throw new Error('Method findIntegrationsByOwnership must be implemented by subclass');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
13
|
/**
|
|
28
14
|
* Find all integrations for a user
|
|
29
15
|
*
|
|
@@ -137,12 +123,10 @@ class IntegrationRepositoryInterface {
|
|
|
137
123
|
* @param {Array<string|number>} entities - Array of entity IDs
|
|
138
124
|
* @param {string|number} userId - User ID
|
|
139
125
|
* @param {Object} config - Integration configuration
|
|
140
|
-
* @param {{organizationId?: (string|number|null)}} [tenancy] - the organization the
|
|
141
|
-
* integration is created in (ADR-056 §3.6)
|
|
142
126
|
* @returns {Promise<Object>} Created integration object
|
|
143
127
|
* @abstract
|
|
144
128
|
*/
|
|
145
|
-
async createIntegration(entities, userId, config
|
|
129
|
+
async createIntegration(entities, userId, config) {
|
|
146
130
|
throw new Error('Method createIntegration must be implemented by subclass');
|
|
147
131
|
}
|
|
148
132
|
|