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