@friggframework/core 2.0.0--canary.397.4957a89.0 → 2.0.0--canary.398.bdb6d27.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 +34 -35
  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 +44 -42
  16. package/integrations/integration-factory.js +251 -0
  17. package/integrations/integration-router.js +178 -301
  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}/index.js +8 -0
  24. package/module-plugin/manager.js +169 -0
  25. package/module-plugin/module-factory.js +61 -0
  26. package/{modules → module-plugin}/test/mock-api/api.js +3 -8
  27. package/{modules → module-plugin}/test/mock-api/definition.js +8 -12
  28. package/package.json +5 -5
  29. package/syncs/sync.js +1 -0
  30. package/types/integrations/index.d.ts +6 -2
  31. package/types/module-plugin/index.d.ts +56 -4
  32. package/types/syncs/index.d.ts +2 -0
  33. package/credential/credential-repository.js +0 -42
  34. package/credential/use-cases/get-credential-for-user.js +0 -21
  35. package/credential/use-cases/update-authentication-status.js +0 -15
  36. package/handlers/app-definition-loader.js +0 -38
  37. package/integrations/integration-repository.js +0 -67
  38. package/integrations/integration.js +0 -233
  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 -72
  51. package/integrations/use-cases/delete-integration-for-user.js +0 -73
  52. package/integrations/use-cases/get-integration-for-user.js +0 -79
  53. package/integrations/use-cases/get-integration-instance.js +0 -84
  54. package/integrations/use-cases/get-integrations-for-user.js +0 -77
  55. package/integrations/use-cases/get-possible-integrations.js +0 -27
  56. package/integrations/use-cases/index.js +0 -11
  57. package/integrations/use-cases/update-integration-messages.js +0 -31
  58. package/integrations/use-cases/update-integration-status.js +0 -28
  59. package/integrations/use-cases/update-integration.js +0 -92
  60. package/integrations/utils/map-integration-dto.js +0 -36
  61. package/modules/module-factory.js +0 -54
  62. package/modules/module-repository.js +0 -107
  63. package/modules/module.js +0 -221
  64. package/modules/tests/doubles/test-module-factory.js +0 -16
  65. package/modules/tests/doubles/test-module-repository.js +0 -19
  66. package/modules/use-cases/get-entities-for-user.js +0 -32
  67. package/modules/use-cases/get-entity-options-by-id.js +0 -58
  68. package/modules/use-cases/get-entity-options-by-type.js +0 -34
  69. package/modules/use-cases/get-module-instance-from-type.js +0 -31
  70. package/modules/use-cases/get-module.js +0 -56
  71. package/modules/use-cases/process-authorization-callback.js +0 -114
  72. package/modules/use-cases/refresh-entity-options.js +0 -58
  73. package/modules/use-cases/test-module-auth.js +0 -54
  74. package/modules/utils/map-module-dto.js +0 -18
  75. package/user/tests/doubles/test-user-repository.js +0 -72
  76. package/user/tests/use-cases/create-individual-user.test.js +0 -24
  77. package/user/tests/use-cases/create-organization-user.test.js +0 -28
  78. package/user/tests/use-cases/create-token-for-user-id.test.js +0 -19
  79. package/user/tests/use-cases/get-user-from-bearer-token.test.js +0 -64
  80. package/user/tests/use-cases/login-user.test.js +0 -140
  81. package/user/use-cases/create-individual-user.js +0 -61
  82. package/user/use-cases/create-organization-user.js +0 -47
  83. package/user/use-cases/create-token-for-user-id.js +0 -30
  84. package/user/use-cases/get-user-from-bearer-token.js +0 -77
  85. package/user/use-cases/login-user.js +0 -122
  86. package/user/user-repository.js +0 -62
  87. package/user/user.js +0 -77
  88. /package/{modules → module-plugin}/ModuleConstants.js +0 -0
  89. /package/{modules → module-plugin}/credential.js +0 -0
  90. /package/{modules → module-plugin}/entity.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,37 +286,31 @@ 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);
308
+ const module = await getModuleInstance(req, params.entityType);
427
309
  const areRequirementsValid =
428
310
  module.validateAuthorizationRequirements();
429
311
  if (!areRequirementsValid) {
430
312
  throw new Error(
431
- `Error: Entity of type ${params.entityType} requires a valid url`
313
+ `Error: EntityManager of type ${params.entityType} requires a valid url`
432
314
  );
433
315
  }
434
316
 
@@ -438,27 +320,23 @@ function setEntityRoutes(router, getUserFromBearerToken, useCases) {
438
320
 
439
321
  router.route('/api/authorize').post(
440
322
  catchAsyncError(async (req, res) => {
441
- const user = await getUserFromBearerToken.execute(
442
- req.headers.authorization
443
- );
444
- const userId = user.getId();
445
323
  const params = checkRequiredParams(req.body, [
446
324
  'entityType',
447
325
  'data',
448
326
  ]);
327
+ const module = await getModuleInstance(req, params.entityType);
449
328
 
450
- const entityDetails = await processAuthorizationCallback.execute(userId, params.entityType, params.data);
451
-
452
- res.json(entityDetails);
329
+ res.json(
330
+ await module.processAuthorizationCallback({
331
+ userId: getUserId(req),
332
+ data: params.data,
333
+ })
334
+ );
453
335
  })
454
336
  );
455
337
 
456
338
  router.route('/api/entity').post(
457
339
  catchAsyncError(async (req, res) => {
458
- const user = await getUserFromBearerToken.execute(
459
- req.headers.authorization
460
- );
461
- const userId = user.getId();
462
340
  const params = checkRequiredParams(req.body, [
463
341
  'entityType',
464
342
  'data',
@@ -466,21 +344,20 @@ function setEntityRoutes(router, getUserFromBearerToken, useCases) {
466
344
  checkRequiredParams(req.body.data, ['credential_id']);
467
345
 
468
346
  // May want to pass along the user ID as well so credential ID's can't be fished???
469
- const credential = await getCredentialForUser.execute(
470
- params.data.credential_id,
471
- userId
347
+ const credential = await IntegrationHelper.getCredentialById(
348
+ params.data.credential_id
472
349
  );
473
350
 
474
351
  if (!credential) {
475
352
  throw Boom.badRequest('Invalid credential ID');
476
353
  }
477
354
 
478
- const module = await getModuleInstanceFromType.execute(userId, params.entityType);
355
+ const module = await getModuleInstance(req, params.entityType);
479
356
  const entityDetails = await module.getEntityDetails(
480
357
  module.api,
481
358
  null,
482
359
  null,
483
- userId
360
+ getUserId(req)
484
361
  );
485
362
 
486
363
  res.json(await module.findOrCreateEntity(entityDetails));
@@ -489,39 +366,36 @@ function setEntityRoutes(router, getUserFromBearerToken, useCases) {
489
366
 
490
367
  router.route('/api/entity/options/:credentialId').get(
491
368
  catchAsyncError(async (req, res) => {
492
- const user = await getUserFromBearerToken.execute(
493
- req.headers.authorization
494
- );
495
- const userId = user.getId();
496
369
  // TODO May want to pass along the user ID as well so credential ID's can't be fished???
497
370
  // TODO **flagging this for review** -MW
498
- const credential = await getCredentialForUser.execute(
499
- req.params.credentialId,
500
- userId
371
+ const credential = await IntegrationHelper.getCredentialById(
372
+ req.params.credentialId
501
373
  );
502
- if (credential.user._id.toString() !== userId) {
374
+ if (credential.user._id.toString() !== getUserId(req)) {
503
375
  throw Boom.forbidden('Credential does not belong to user');
504
376
  }
505
377
 
506
378
  const params = checkRequiredParams(req.query, ['entityType']);
507
- const entityOptions = await getEntityOptionsByType.execute(userId, params.entityType);
379
+ const module = await getModuleInstance(req, params.entityType);
508
380
 
509
- res.json(entityOptions);
381
+ res.json(await module.getEntityOptions());
510
382
  })
511
383
  );
512
384
 
513
385
  router.route('/api/entities/:entityId/test-auth').get(
514
386
  catchAsyncError(async (req, res) => {
515
- const user = await getUserFromBearerToken.execute(
516
- req.headers.authorization
517
- );
518
- const userId = user.getId();
519
387
  const params = checkRequiredParams(req.params, ['entityId']);
520
- const testAuthResponse = await testModuleAuth.execute(
388
+ const module = await moduleFactory.getModuleInstanceFromEntityId(
521
389
  params.entityId,
522
- userId
390
+ getUserId(req)
523
391
  );
524
392
 
393
+ if (!module) {
394
+ throw Boom.notFound();
395
+ }
396
+
397
+ const testAuthResponse = await module.testAuth();
398
+
525
399
  if (!testAuthResponse) {
526
400
  res.status(400);
527
401
  res.json({
@@ -541,52 +415,55 @@ function setEntityRoutes(router, getUserFromBearerToken, useCases) {
541
415
 
542
416
  router.route('/api/entities/:entityId').get(
543
417
  catchAsyncError(async (req, res) => {
544
- const user = await getUserFromBearerToken.execute(
545
- req.headers.authorization
546
- );
547
- const userId = user.getId();
548
418
  const params = checkRequiredParams(req.params, ['entityId']);
549
- const module = await getModule.execute(
419
+ const module = await moduleFactory.getModuleInstanceFromEntityId(
550
420
  params.entityId,
551
- userId
421
+ getUserId(req)
552
422
  );
553
423
 
554
- res.json(module);
424
+ if (!module) {
425
+ throw Boom.notFound();
426
+ }
427
+
428
+ res.json(module.entity);
555
429
  })
556
430
  );
557
431
 
558
432
  router.route('/api/entities/:entityId/options').post(
559
433
  catchAsyncError(async (req, res) => {
560
- const user = await getUserFromBearerToken.execute(
561
- req.headers.authorization
562
- );
563
- const userId = user.getId();
564
434
  const params = checkRequiredParams(req.params, [
565
435
  'entityId',
436
+ getUserId(req),
566
437
  ]);
438
+ const module = await moduleFactory.getModuleInstanceFromEntityId(
439
+ params.entityId,
440
+ getUserId(req)
441
+ );
567
442
 
568
- const entityOptions = await getEntityOptionsById.execute(params.entityId, userId);
443
+ if (!module) {
444
+ throw Boom.notFound();
445
+ }
569
446
 
570
- res.json(entityOptions);
447
+ res.json(await module.getEntityOptions());
571
448
  })
572
449
  );
573
450
 
574
451
  router.route('/api/entities/:entityId/options/refresh').post(
575
452
  catchAsyncError(async (req, res) => {
576
- const user = await getUserFromBearerToken.execute(
577
- req.headers.authorization
578
- );
579
- const userId = user.getId();
580
453
  const params = checkRequiredParams(req.params, [
581
454
  'entityId',
455
+ getUserId(req),
582
456
  ]);
583
- const updatedOptions = await refreshEntityOptions.execute(
457
+ const module = await moduleFactory.getModuleInstanceFromEntityId(
584
458
  params.entityId,
585
- userId,
586
- req.body
459
+ getUserId(req)
587
460
  );
588
461
 
589
- res.json(updatedOptions);
462
+ if (!module) {
463
+ throw Boom.notFound();
464
+ }
465
+
466
+ res.json(await module.refreshEntityOptions(req.body));
590
467
  })
591
468
  );
592
469
  }