@friggframework/core 2.0.0--canary.395.65f5f64.0 → 2.0.0--canary.398.24926ac.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.
Files changed (97) hide show
  1. package/README.md +50 -931
  2. package/core/create-handler.js +0 -1
  3. package/database/models/WebsocketConnection.js +5 -0
  4. package/handlers/app-handler-helpers.js +3 -0
  5. package/handlers/backend-utils.js +44 -42
  6. package/handlers/routers/auth.js +14 -3
  7. package/handlers/routers/integration-defined-routers.js +5 -8
  8. package/handlers/routers/middleware/loadUser.js +15 -0
  9. package/handlers/routers/middleware/requireLoggedInUser.js +12 -0
  10. package/handlers/routers/user.js +5 -25
  11. package/handlers/workers/integration-defined-workers.js +3 -6
  12. package/index.js +16 -1
  13. package/integrations/create-frigg-backend.js +31 -0
  14. package/integrations/index.js +5 -0
  15. package/integrations/integration-base.js +46 -142
  16. package/integrations/integration-factory.js +251 -0
  17. package/integrations/integration-router.js +181 -303
  18. package/integrations/integration-user.js +144 -0
  19. package/integrations/options.js +1 -1
  20. package/integrations/test/integration-base.test.js +144 -0
  21. package/module-plugin/auther.js +393 -0
  22. package/module-plugin/entity-manager.js +70 -0
  23. package/{modules → module-plugin}/entity.js +0 -1
  24. package/{modules → module-plugin}/index.js +8 -0
  25. package/module-plugin/manager.js +169 -0
  26. package/module-plugin/module-factory.js +61 -0
  27. package/{modules → module-plugin}/test/mock-api/api.js +3 -8
  28. package/{modules → module-plugin}/test/mock-api/definition.js +8 -12
  29. package/package.json +5 -5
  30. package/syncs/sync.js +1 -0
  31. package/types/integrations/index.d.ts +6 -2
  32. package/types/module-plugin/index.d.ts +56 -4
  33. package/types/syncs/index.d.ts +2 -0
  34. package/credential/credential-repository.js +0 -56
  35. package/credential/use-cases/get-credential-for-user.js +0 -21
  36. package/credential/use-cases/update-authentication-status.js +0 -15
  37. package/handlers/app-definition-loader.js +0 -38
  38. package/integrations/integration-repository.js +0 -80
  39. package/integrations/tests/doubles/dummy-integration-class.js +0 -90
  40. package/integrations/tests/doubles/test-integration-repository.js +0 -89
  41. package/integrations/tests/use-cases/create-integration.test.js +0 -124
  42. package/integrations/tests/use-cases/delete-integration-for-user.test.js +0 -143
  43. package/integrations/tests/use-cases/get-integration-for-user.test.js +0 -143
  44. package/integrations/tests/use-cases/get-integration-instance.test.js +0 -169
  45. package/integrations/tests/use-cases/get-integrations-for-user.test.js +0 -169
  46. package/integrations/tests/use-cases/get-possible-integrations.test.js +0 -188
  47. package/integrations/tests/use-cases/update-integration-messages.test.js +0 -142
  48. package/integrations/tests/use-cases/update-integration-status.test.js +0 -103
  49. package/integrations/tests/use-cases/update-integration.test.js +0 -134
  50. package/integrations/use-cases/create-integration.js +0 -71
  51. package/integrations/use-cases/delete-integration-for-user.js +0 -72
  52. package/integrations/use-cases/get-integration-for-user.js +0 -78
  53. package/integrations/use-cases/get-integration-instance-by-definition.js +0 -67
  54. package/integrations/use-cases/get-integration-instance.js +0 -82
  55. package/integrations/use-cases/get-integrations-for-user.js +0 -76
  56. package/integrations/use-cases/get-possible-integrations.js +0 -27
  57. package/integrations/use-cases/index.js +0 -11
  58. package/integrations/use-cases/update-integration-messages.js +0 -31
  59. package/integrations/use-cases/update-integration-status.js +0 -28
  60. package/integrations/use-cases/update-integration.js +0 -91
  61. package/integrations/utils/map-integration-dto.js +0 -36
  62. package/modules/module-factory.js +0 -54
  63. package/modules/module-repository.js +0 -107
  64. package/modules/module.js +0 -218
  65. package/modules/tests/doubles/test-module-factory.js +0 -16
  66. package/modules/tests/doubles/test-module-repository.js +0 -19
  67. package/modules/use-cases/get-entities-for-user.js +0 -32
  68. package/modules/use-cases/get-entity-options-by-id.js +0 -58
  69. package/modules/use-cases/get-entity-options-by-type.js +0 -34
  70. package/modules/use-cases/get-module-instance-from-type.js +0 -31
  71. package/modules/use-cases/get-module.js +0 -56
  72. package/modules/use-cases/process-authorization-callback.js +0 -108
  73. package/modules/use-cases/refresh-entity-options.js +0 -58
  74. package/modules/use-cases/test-module-auth.js +0 -54
  75. package/modules/utils/map-module-dto.js +0 -18
  76. package/user/tests/doubles/test-user-repository.js +0 -72
  77. package/user/tests/use-cases/create-individual-user.test.js +0 -24
  78. package/user/tests/use-cases/create-organization-user.test.js +0 -28
  79. package/user/tests/use-cases/create-token-for-user-id.test.js +0 -19
  80. package/user/tests/use-cases/get-user-from-bearer-token.test.js +0 -64
  81. package/user/tests/use-cases/login-user.test.js +0 -140
  82. package/user/use-cases/create-individual-user.js +0 -61
  83. package/user/use-cases/create-organization-user.js +0 -47
  84. package/user/use-cases/create-token-for-user-id.js +0 -30
  85. package/user/use-cases/get-user-from-bearer-token.js +0 -77
  86. package/user/use-cases/login-user.js +0 -122
  87. package/user/user-repository.js +0 -62
  88. package/user/user.js +0 -77
  89. /package/{modules → module-plugin}/ModuleConstants.js +0 -0
  90. /package/{modules → module-plugin}/credential.js +0 -0
  91. /package/{modules → module-plugin}/requester/api-key.js +0 -0
  92. /package/{modules → module-plugin}/requester/basic.js +0 -0
  93. /package/{modules → module-plugin}/requester/oauth-2.js +0 -0
  94. /package/{modules → module-plugin}/requester/requester.js +0 -0
  95. /package/{modules → module-plugin}/requester/requester.test.js +0 -0
  96. /package/{modules → module-plugin}/test/auther.test.js +0 -0
  97. /package/{modules → module-plugin}/test/mock-api/mocks/hubspot.js +0 -0
@@ -2,144 +2,23 @@ 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 { IntegrationRepository } = require('./integration-repository');
6
- const { DeleteIntegrationForUser } = require('./use-cases/delete-integration-for-user');
7
- const { GetIntegrationsForUser } = require('./use-cases/get-integrations-for-user');
8
- const { CredentialRepository } = require('../credential/credential-repository');
9
- const { GetCredentialForUser } = require('../credential/use-cases/get-credential-for-user');
10
- const { CreateIntegration } = require('./use-cases/create-integration');
11
- const { ModuleFactory } = require('../modules/module-factory');
12
- const { ModuleRepository } = require('../modules/module-repository');
13
- const { GetEntitiesForUser } = require('../modules/use-cases/get-entities-for-user');
14
- const { loadAppDefinition } = require('../handlers/app-definition-loader');
15
- const { GetIntegrationInstance } = require('./use-cases/get-integration-instance');
16
- const { UpdateIntegration } = require('./use-cases/update-integration');
17
- const { getModulesDefinitionFromIntegrationClasses } = require('./utils/map-integration-dto');
18
- const { GetModuleInstanceFromType } = require('../modules/use-cases/get-module-instance-from-type');
19
- const { GetEntityOptionsByType } = require('../modules/use-cases/get-entity-options-by-type');
20
- const { TestModuleAuth } = require('../modules/use-cases/test-module-auth');
21
- const { GetModule } = require('../modules/use-cases/get-module');
22
- const { GetEntityOptionsById } = require('../modules/use-cases/get-entity-options-by-id');
23
- const { RefreshEntityOptions } = require('../modules/use-cases/refresh-entity-options');
24
- const { GetPossibleIntegrations } = require('./use-cases/get-possible-integrations');
25
- const { UserRepository } = require('../user/user-repository');
26
- const { GetUserFromBearerToken } = require('../user/use-cases/get-user-from-bearer-token');
27
- const { ProcessAuthorizationCallback } = require('../modules/use-cases/process-authorization-callback');
28
-
29
- function createIntegrationRouter() {
30
- const { integrations: integrationClasses, userConfig } = loadAppDefinition();
31
- const moduleRepository = new ModuleRepository();
32
- const integrationRepository = new IntegrationRepository();
33
- const credentialRepository = new CredentialRepository();
34
- const userRepository = new UserRepository({ userConfig });
35
-
36
- const getUserFromBearerToken = new GetUserFromBearerToken({
37
- userRepository,
38
- userConfig,
39
- });
40
-
41
- const moduleFactory = new ModuleFactory({
42
- moduleRepository,
43
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
44
- });
45
- const deleteIntegrationForUser = new DeleteIntegrationForUser({
46
- integrationRepository,
47
- integrationClasses,
48
- });
49
-
50
- const getIntegrationsForUser = new GetIntegrationsForUser({
51
- integrationRepository,
52
- integrationClasses,
53
- moduleFactory,
54
- moduleRepository,
55
- });
56
-
57
- const getCredentialForUser = new GetCredentialForUser({
58
- credentialRepository,
59
- });
60
-
61
- const createIntegration = new CreateIntegration({
62
- integrationRepository,
63
- integrationClasses,
64
- moduleFactory,
65
- });
66
-
67
- const getEntitiesForUser = new GetEntitiesForUser({
68
- moduleRepository,
69
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
70
- });
71
-
72
- const getIntegrationInstance = new GetIntegrationInstance({
73
- integrationRepository,
74
- integrationClasses,
75
- moduleFactory,
76
- });
77
-
78
- const updateIntegration = new UpdateIntegration({
79
- integrationRepository,
80
- integrationClasses,
81
- moduleFactory,
82
- });
83
-
84
- const getModuleInstanceFromType = new GetModuleInstanceFromType({
85
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
86
- });
87
-
88
- const getEntityOptionsByType = new GetEntityOptionsByType({
89
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
90
- });
91
-
92
- const testModuleAuth = new TestModuleAuth({
93
- moduleRepository,
94
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
95
- });
96
-
97
- const getModule = new GetModule({
98
- moduleRepository,
99
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
100
- });
101
-
102
- const getEntityOptionsById = new GetEntityOptionsById({
103
- moduleRepository,
104
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
105
- });
106
-
107
- const refreshEntityOptions = new RefreshEntityOptions({
108
- moduleRepository,
109
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
110
- });
111
-
112
- const getPossibleIntegrations = new GetPossibleIntegrations({
113
- integrationClasses,
114
- });
115
-
116
- const processAuthorizationCallback = new ProcessAuthorizationCallback({
117
- moduleRepository,
118
- credentialRepository,
119
- moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
120
- });
121
-
122
- const router = express();
123
-
124
- setIntegrationRoutes(router, getUserFromBearerToken, {
125
- createIntegration,
126
- deleteIntegrationForUser,
127
- getIntegrationsForUser,
128
- getEntitiesForUser,
129
- getIntegrationInstance,
130
- updateIntegration,
131
- getPossibleIntegrations,
132
- });
133
- setEntityRoutes(router, getUserFromBearerToken, {
134
- getCredentialForUser,
135
- getModuleInstanceFromType,
136
- getEntityOptionsByType,
137
- testModuleAuth,
138
- getModule,
139
- getEntityOptionsById,
140
- refreshEntityOptions,
141
- processAuthorizationCallback,
142
- });
5
+ const { debug } = require('../logs');
6
+ function createIntegrationRouter(params) {
7
+ const router = get(params, 'router', express());
8
+ const factory = get(params, 'factory');
9
+ const getUserId = get(params, 'getUserId', (req) => null);
10
+ const requireLoggedInUser = get(
11
+ params,
12
+ 'requireLoggedInUser',
13
+ (req, res, next) => next()
14
+ );
15
+
16
+ router.all('/api/entities*', requireLoggedInUser);
17
+ router.all('/api/authorize', requireLoggedInUser);
18
+ router.all('/api/integrations*', requireLoggedInUser);
19
+
20
+ setIntegrationRoutes(router, factory, getUserId);
21
+ setEntityRoutes(router, factory, getUserId);
143
22
  return router;
144
23
  }
145
24
 
@@ -157,103 +36,121 @@ function checkRequiredParams(params, requiredKeys) {
157
36
 
158
37
  if (missingKeys.length > 0) {
159
38
  throw Boom.badRequest(
160
- `Missing Parameter${missingKeys.length === 1 ? '' : 's'
161
- }: ${missingKeys.join(', ')} ${missingKeys.length === 1 ? 'is' : 'are'
39
+ `Missing Parameter${
40
+ missingKeys.length === 1 ? '' : 's'
41
+ }: ${missingKeys.join(', ')} ${
42
+ missingKeys.length === 1 ? 'is' : 'are'
162
43
  } required.`
163
44
  );
164
45
  }
165
46
  return returnDict;
166
47
  }
167
48
 
168
- /**
169
- * Sets up integration-related routes on the provided Express router
170
- * @param {express.Router} router - Express router instance to add routes to
171
- * @param {import('../user/use-cases/get-user-from-bearer-token').GetUserFromBearerToken} getUserFromBearerToken - Use case for retrieving a user from a bearer token
172
- * @param {Object} useCases - use cases for integration management
173
- */
174
- function setIntegrationRoutes(router, getUserFromBearerToken, useCases) {
175
- const {
176
- createIntegration,
177
- deleteIntegrationForUser,
178
- getIntegrationsForUser,
179
- getEntitiesForUser,
180
- getIntegrationInstance,
181
- updateIntegration,
182
- getPossibleIntegrations,
183
- } = useCases;
49
+ function setIntegrationRoutes(router, factory, getUserId) {
50
+ const { moduleFactory, integrationFactory, IntegrationHelper } = factory;
184
51
  router.route('/api/integrations').get(
185
52
  catchAsyncError(async (req, res) => {
186
- const user = await getUserFromBearerToken.execute(
187
- req.headers.authorization
188
- );
189
- const userId = user.getId();
190
- const integrations = await getIntegrationsForUser.execute(userId);
191
- const results = {
192
- entities: {
193
- options: await getPossibleIntegrations.execute(),
194
- authorized: await getEntitiesForUser.execute(userId),
195
- },
196
- integrations: integrations,
197
- }
53
+ const results = await integrationFactory.getIntegrationOptions();
54
+ results.entities.authorized =
55
+ await moduleFactory.getEntitiesForUser(getUserId(req));
56
+ results.integrations =
57
+ await IntegrationHelper.getIntegrationsForUserId(
58
+ getUserId(req)
59
+ );
198
60
 
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
+ }
199
69
  res.json(results);
200
70
  })
201
71
  );
202
72
 
203
73
  router.route('/api/integrations').post(
204
74
  catchAsyncError(async (req, res) => {
205
- const user = await getUserFromBearerToken.execute(
206
- req.headers.authorization
207
- );
208
- const userId = user.getId();
209
75
  const params = checkRequiredParams(req.body, [
210
76
  'entities',
211
77
  'config',
212
78
  ]);
213
-
79
+ // throw if not value
214
80
  get(params.config, 'type');
215
81
 
216
- const integration = await createIntegration.execute(
82
+ // create integration
83
+ const integration = await integrationFactory.createIntegration(
217
84
  params.entities,
218
- userId,
85
+ getUserId(req),
219
86
  params.config
220
87
  );
221
88
 
222
- res.status(201).json(integration);
89
+ // post integration initialization
90
+ debug(
91
+ `Calling onCreate on the ${integration?.constructor?.Config?.name} Integration with no arguments`
92
+ );
93
+ await integration.send('ON_CREATE', {});
94
+
95
+ res.status(201).json(
96
+ await IntegrationHelper.getFormattedIntegration(
97
+ integration.record
98
+ )
99
+ );
223
100
  })
224
101
  );
225
102
 
226
103
  router.route('/api/integrations/:integrationId').patch(
227
104
  catchAsyncError(async (req, res) => {
228
- const user = await getUserFromBearerToken.execute(
229
- req.headers.authorization
230
- );
231
- const userId = user.getId();
232
105
  const params = checkRequiredParams(req.body, ['config']);
233
106
 
234
- const integration = await updateIntegration.execute(req.params.integrationId, userId, params.config);
235
- res.json(integration);
107
+ const integration =
108
+ await integrationFactory.getInstanceFromIntegrationId({
109
+ integrationId: req.params.integrationId,
110
+ userId: getUserId(req),
111
+ });
112
+
113
+ debug(
114
+ `Calling onUpdate on the ${integration?.constructor?.Config?.name} Integration arguments: `,
115
+ params
116
+ );
117
+ await integration.send('ON_UPDATE', params);
118
+
119
+ res.json(
120
+ await IntegrationHelper.getFormattedIntegration(
121
+ integration.record
122
+ )
123
+ );
236
124
  })
237
125
  );
238
126
 
239
127
  router.route('/api/integrations/:integrationId').delete(
240
128
  catchAsyncError(async (req, res) => {
241
- const user = await getUserFromBearerToken.execute(
242
- req.headers.authorization
243
- );
244
129
  const params = checkRequiredParams(req.params, ['integrationId']);
245
- await deleteIntegrationForUser.execute(params.integrationId, user.getId());
246
- res.status(204).json({});
130
+ const integration =
131
+ await integrationFactory.getInstanceFromIntegrationId({
132
+ userId: getUserId(req),
133
+ integrationId: params.integrationId,
134
+ });
135
+
136
+ debug(
137
+ `Calling onUpdate on the ${integration?.constructor?.Definition?.name} Integration with no arguments`
138
+ );
139
+ await integration.send('ON_DELETE');
140
+ await IntegrationHelper.deleteIntegrationForUserById(
141
+ getUserId(req),
142
+ params.integrationId
143
+ );
144
+
145
+ res.status(201).json({});
247
146
  })
248
147
  );
249
148
 
250
149
  router.route('/api/integrations/:integrationId/config/options').get(
251
150
  catchAsyncError(async (req, res) => {
252
- const user = await getUserFromBearerToken.execute(
253
- req.headers.authorization
254
- );
255
151
  const params = checkRequiredParams(req.params, ['integrationId']);
256
- const integration = await getIntegrationInstance.execute(params.integrationId, user.getId());
152
+ const integration =
153
+ await integrationFactory.getInstanceFromIntegrationId(params);
257
154
  res.json(await integration.send('GET_CONFIG_OPTIONS'));
258
155
  })
259
156
  );
@@ -262,13 +159,13 @@ function setIntegrationRoutes(router, getUserFromBearerToken, useCases) {
262
159
  .route('/api/integrations/:integrationId/config/options/refresh')
263
160
  .post(
264
161
  catchAsyncError(async (req, res) => {
265
- const user = await getUserFromBearerToken.execute(
266
- req.headers.authorization
267
- );
268
162
  const params = checkRequiredParams(req.params, [
269
163
  'integrationId',
270
164
  ]);
271
- const integration = await getIntegrationInstance.execute(params.integrationId, user.getId());
165
+ const integration =
166
+ await integrationFactory.getInstanceFromIntegrationId(
167
+ params
168
+ );
272
169
 
273
170
  res.json(
274
171
  await integration.send('REFRESH_CONFIG_OPTIONS', req.body)
@@ -277,11 +174,9 @@ function setIntegrationRoutes(router, getUserFromBearerToken, useCases) {
277
174
  );
278
175
  router.route('/api/integrations/:integrationId/actions').all(
279
176
  catchAsyncError(async (req, res) => {
280
- const user = await getUserFromBearerToken.execute(
281
- req.headers.authorization
282
- );
283
177
  const params = checkRequiredParams(req.params, ['integrationId']);
284
- const integration = await getIntegrationInstance.execute(params.integrationId, user.getId());
178
+ const integration =
179
+ await integrationFactory.getInstanceFromIntegrationId(params);
285
180
  res.json(await integration.send('GET_USER_ACTIONS', req.body));
286
181
  })
287
182
  );
@@ -290,14 +185,14 @@ function setIntegrationRoutes(router, getUserFromBearerToken, useCases) {
290
185
  .route('/api/integrations/:integrationId/actions/:actionId/options')
291
186
  .all(
292
187
  catchAsyncError(async (req, res) => {
293
- const user = await getUserFromBearerToken.execute(
294
- req.headers.authorization
295
- );
296
188
  const params = checkRequiredParams(req.params, [
297
189
  'integrationId',
298
190
  'actionId',
299
191
  ]);
300
- const integration = await getIntegrationInstance.execute(params.integrationId, user.getId());
192
+ const integration =
193
+ await integrationFactory.getInstanceFromIntegrationId(
194
+ params
195
+ );
301
196
 
302
197
  res.json(
303
198
  await integration.send('GET_USER_ACTION_OPTIONS', {
@@ -314,14 +209,14 @@ function setIntegrationRoutes(router, getUserFromBearerToken, useCases) {
314
209
  )
315
210
  .post(
316
211
  catchAsyncError(async (req, res) => {
317
- const user = await getUserFromBearerToken.execute(
318
- req.headers.authorization
319
- );
320
212
  const params = checkRequiredParams(req.params, [
321
213
  'integrationId',
322
214
  'actionId',
323
215
  ]);
324
- const integration = await getIntegrationInstance.execute(params.integrationId, user.getId());
216
+ const integration =
217
+ await integrationFactory.getInstanceFromIntegrationId(
218
+ params
219
+ );
325
220
 
326
221
  res.json(
327
222
  await integration.send('REFRESH_USER_ACTION_OPTIONS', {
@@ -334,31 +229,23 @@ function setIntegrationRoutes(router, getUserFromBearerToken, useCases) {
334
229
 
335
230
  router.route('/api/integrations/:integrationId/actions/:actionId').post(
336
231
  catchAsyncError(async (req, res) => {
337
- const user = await getUserFromBearerToken.execute(
338
- req.headers.authorization
339
- );
340
232
  const params = checkRequiredParams(req.params, [
341
233
  'integrationId',
342
234
  'actionId',
343
235
  ]);
344
- const integration = await getIntegrationInstance.execute(params.integrationId, user.getId());
236
+ const integration =
237
+ await integrationFactory.getInstanceFromIntegrationId(params);
238
+
345
239
  res.json(await integration.send(params.actionId, req.body));
346
240
  })
347
241
  );
348
242
 
349
243
  router.route('/api/integrations/:integrationId').get(
350
244
  catchAsyncError(async (req, res) => {
351
- const user = await getUserFromBearerToken.execute(
352
- req.headers.authorization
353
- );
354
-
355
- if (!user) {
356
- throw Boom.forbidden('User not found');
357
- }
358
-
359
245
  const params = checkRequiredParams(req.params, ['integrationId']);
360
- const integration = await getIntegrationInstance.execute(params.integrationId, user.getId());
361
-
246
+ const integration = await IntegrationHelper.getIntegrationById(
247
+ params.integrationId
248
+ );
362
249
  // We could perhaps augment router with dynamic options? Haven't decided yet, but here may be the place
363
250
 
364
251
  res.json({
@@ -372,11 +259,12 @@ function setIntegrationRoutes(router, getUserFromBearerToken, useCases) {
372
259
 
373
260
  router.route('/api/integrations/:integrationId/test-auth').get(
374
261
  catchAsyncError(async (req, res) => {
375
- const user = await getUserFromBearerToken.execute(
376
- req.headers.authorization
377
- );
378
262
  const params = checkRequiredParams(req.params, ['integrationId']);
379
- const instance = await getIntegrationInstance.execute(params.integrationId, user.getId());
263
+ const instance =
264
+ await integrationFactory.getInstanceFromIntegrationId({
265
+ userId: getUserId(req),
266
+ integrationId: params.integrationId,
267
+ });
380
268
 
381
269
  if (!instance) {
382
270
  throw Boom.notFound();
@@ -398,66 +286,57 @@ function setIntegrationRoutes(router, getUserFromBearerToken, useCases) {
398
286
  );
399
287
  }
400
288
 
401
-
402
- /**
403
- * Sets up entity-related routes for the integration router
404
- * @param {Object} router - Express router instance
405
- * @param {import('../user/use-cases/get-user-from-bearer-token').GetUserFromBearerToken} getUserFromBearerToken - Use case for retrieving a user from a bearer token
406
- */
407
- function setEntityRoutes(router, getUserFromBearerToken, useCases) {
408
- const {
409
- getCredentialForUser,
410
- getModuleInstanceFromType,
411
- getEntityOptionsByType,
412
- testModuleAuth,
413
- getModule,
414
- getEntityOptionsById,
415
- refreshEntityOptions,
416
- processAuthorizationCallback,
417
- } = useCases;
289
+ function setEntityRoutes(router, factory, getUserId) {
290
+ const { moduleFactory, IntegrationHelper } = factory;
291
+ const getModuleInstance = async (req, entityType) => {
292
+ if (!moduleFactory.checkIsValidType(entityType)) {
293
+ throw Boom.badRequest(
294
+ `Error: Invalid entity type of ${entityType}, options are ${moduleFactory.moduleTypes.join(
295
+ ', '
296
+ )}`
297
+ );
298
+ }
299
+ return await moduleFactory.getInstanceFromTypeName(
300
+ entityType,
301
+ getUserId(req)
302
+ );
303
+ };
418
304
 
419
305
  router.route('/api/authorize').get(
420
306
  catchAsyncError(async (req, res) => {
421
- const user = await getUserFromBearerToken.execute(
422
- req.headers.authorization
423
- );
424
- const userId = user.getId();
425
307
  const params = checkRequiredParams(req.query, ['entityType']);
426
- const module = await getModuleInstanceFromType.execute(userId, params.entityType);
427
- const areRequirementsValid = module.validateAuthorizationRequirements();
308
+ const module = await getModuleInstance(req, params.entityType);
309
+ const areRequirementsValid =
310
+ module.validateAuthorizationRequirements();
428
311
  if (!areRequirementsValid) {
429
312
  throw new Error(
430
- `Error: Entity of type ${params.entityType} requires a valid url`
313
+ `Error: EntityManager of type ${params.entityType} requires a valid url`
431
314
  );
432
315
  }
433
316
 
434
- res.json(module.getAuthorizationRequirements());
317
+ res.json(await module.getAuthorizationRequirements());
435
318
  })
436
319
  );
437
320
 
438
321
  router.route('/api/authorize').post(
439
322
  catchAsyncError(async (req, res) => {
440
- const user = await getUserFromBearerToken.execute(
441
- req.headers.authorization
442
- );
443
- const userId = user.getId();
444
323
  const params = checkRequiredParams(req.body, [
445
324
  'entityType',
446
325
  'data',
447
326
  ]);
327
+ const module = await getModuleInstance(req, params.entityType);
448
328
 
449
- const entityDetails = await processAuthorizationCallback.execute(userId, params.entityType, params.data);
450
-
451
- res.json(entityDetails);
329
+ res.json(
330
+ await module.processAuthorizationCallback({
331
+ userId: getUserId(req),
332
+ data: params.data,
333
+ })
334
+ );
452
335
  })
453
336
  );
454
337
 
455
338
  router.route('/api/entity').post(
456
339
  catchAsyncError(async (req, res) => {
457
- const user = await getUserFromBearerToken.execute(
458
- req.headers.authorization
459
- );
460
- const userId = user.getId();
461
340
  const params = checkRequiredParams(req.body, [
462
341
  'entityType',
463
342
  'data',
@@ -465,21 +344,20 @@ function setEntityRoutes(router, getUserFromBearerToken, useCases) {
465
344
  checkRequiredParams(req.body.data, ['credential_id']);
466
345
 
467
346
  // May want to pass along the user ID as well so credential ID's can't be fished???
468
- const credential = await getCredentialForUser.execute(
469
- params.data.credential_id,
470
- userId
347
+ const credential = await IntegrationHelper.getCredentialById(
348
+ params.data.credential_id
471
349
  );
472
350
 
473
351
  if (!credential) {
474
352
  throw Boom.badRequest('Invalid credential ID');
475
353
  }
476
354
 
477
- const module = await getModuleInstanceFromType.execute(userId, params.entityType);
355
+ const module = await getModuleInstance(req, params.entityType);
478
356
  const entityDetails = await module.getEntityDetails(
479
357
  module.api,
480
358
  null,
481
359
  null,
482
- userId
360
+ getUserId(req)
483
361
  );
484
362
 
485
363
  res.json(await module.findOrCreateEntity(entityDetails));
@@ -488,39 +366,36 @@ function setEntityRoutes(router, getUserFromBearerToken, useCases) {
488
366
 
489
367
  router.route('/api/entity/options/:credentialId').get(
490
368
  catchAsyncError(async (req, res) => {
491
- const user = await getUserFromBearerToken.execute(
492
- req.headers.authorization
493
- );
494
- const userId = user.getId();
495
369
  // TODO May want to pass along the user ID as well so credential ID's can't be fished???
496
370
  // TODO **flagging this for review** -MW
497
- const credential = await getCredentialForUser.execute(
498
- req.params.credentialId,
499
- userId
371
+ const credential = await IntegrationHelper.getCredentialById(
372
+ req.params.credentialId
500
373
  );
501
- if (credential.user._id.toString() !== userId) {
374
+ if (credential.user._id.toString() !== getUserId(req)) {
502
375
  throw Boom.forbidden('Credential does not belong to user');
503
376
  }
504
377
 
505
378
  const params = checkRequiredParams(req.query, ['entityType']);
506
- const entityOptions = await getEntityOptionsByType.execute(userId, params.entityType);
379
+ const module = await getModuleInstance(req, params.entityType);
507
380
 
508
- res.json(entityOptions);
381
+ res.json(await module.getEntityOptions());
509
382
  })
510
383
  );
511
384
 
512
385
  router.route('/api/entities/:entityId/test-auth').get(
513
386
  catchAsyncError(async (req, res) => {
514
- const user = await getUserFromBearerToken.execute(
515
- req.headers.authorization
516
- );
517
- const userId = user.getId();
518
387
  const params = checkRequiredParams(req.params, ['entityId']);
519
- const testAuthResponse = await testModuleAuth.execute(
388
+ const module = await moduleFactory.getModuleInstanceFromEntityId(
520
389
  params.entityId,
521
- userId
390
+ getUserId(req)
522
391
  );
523
392
 
393
+ if (!module) {
394
+ throw Boom.notFound();
395
+ }
396
+
397
+ const testAuthResponse = await module.testAuth();
398
+
524
399
  if (!testAuthResponse) {
525
400
  res.status(400);
526
401
  res.json({
@@ -540,52 +415,55 @@ function setEntityRoutes(router, getUserFromBearerToken, useCases) {
540
415
 
541
416
  router.route('/api/entities/:entityId').get(
542
417
  catchAsyncError(async (req, res) => {
543
- const user = await getUserFromBearerToken.execute(
544
- req.headers.authorization
545
- );
546
- const userId = user.getId();
547
418
  const params = checkRequiredParams(req.params, ['entityId']);
548
- const module = await getModule.execute(
419
+ const module = await moduleFactory.getModuleInstanceFromEntityId(
549
420
  params.entityId,
550
- userId
421
+ getUserId(req)
551
422
  );
552
423
 
553
- res.json(module);
424
+ if (!module) {
425
+ throw Boom.notFound();
426
+ }
427
+
428
+ res.json(module.entity);
554
429
  })
555
430
  );
556
431
 
557
432
  router.route('/api/entities/:entityId/options').post(
558
433
  catchAsyncError(async (req, res) => {
559
- const user = await getUserFromBearerToken.execute(
560
- req.headers.authorization
561
- );
562
- const userId = user.getId();
563
434
  const params = checkRequiredParams(req.params, [
564
435
  'entityId',
436
+ getUserId(req),
565
437
  ]);
438
+ const module = await moduleFactory.getModuleInstanceFromEntityId(
439
+ params.entityId,
440
+ getUserId(req)
441
+ );
566
442
 
567
- const entityOptions = await getEntityOptionsById.execute(params.entityId, userId);
443
+ if (!module) {
444
+ throw Boom.notFound();
445
+ }
568
446
 
569
- res.json(entityOptions);
447
+ res.json(await module.getEntityOptions());
570
448
  })
571
449
  );
572
450
 
573
451
  router.route('/api/entities/:entityId/options/refresh').post(
574
452
  catchAsyncError(async (req, res) => {
575
- const user = await getUserFromBearerToken.execute(
576
- req.headers.authorization
577
- );
578
- const userId = user.getId();
579
453
  const params = checkRequiredParams(req.params, [
580
454
  'entityId',
455
+ getUserId(req),
581
456
  ]);
582
- const updatedOptions = await refreshEntityOptions.execute(
457
+ const module = await moduleFactory.getModuleInstanceFromEntityId(
583
458
  params.entityId,
584
- userId,
585
- req.body
459
+ getUserId(req)
586
460
  );
587
461
 
588
- res.json(updatedOptions);
462
+ if (!module) {
463
+ throw Boom.notFound();
464
+ }
465
+
466
+ res.json(await module.refreshEntityOptions(req.body));
589
467
  })
590
468
  );
591
469
  }