@friggframework/core 2.0.0--canary.393.5a4db58.0 → 2.0.0--canary.395.d07514c.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 (31) hide show
  1. package/handlers/app-handler-helpers.js +0 -3
  2. package/handlers/backend-utils.js +34 -16
  3. package/handlers/routers/auth.js +18 -9
  4. package/handlers/routers/integration-defined-routers.js +7 -2
  5. package/handlers/routers/user.js +25 -5
  6. package/handlers/workers/integration-defined-workers.js +5 -1
  7. package/index.js +0 -2
  8. package/integrations/index.js +0 -2
  9. package/integrations/integration-factory.js +5 -6
  10. package/integrations/integration-router.js +133 -43
  11. package/module-plugin/auther.js +3 -2
  12. package/module-plugin/test/mock-api/api.js +8 -3
  13. package/module-plugin/test/mock-api/definition.js +12 -8
  14. package/package.json +5 -5
  15. package/user/tests/doubles/test-user-repository.js +115 -0
  16. package/user/tests/use-cases/create-individual-user.test.js +24 -0
  17. package/user/tests/use-cases/create-organization-user.test.js +28 -0
  18. package/user/tests/use-cases/create-token-for-user-id.test.js +19 -0
  19. package/user/tests/use-cases/get-user-from-bearer-token.test.js +64 -0
  20. package/user/tests/use-cases/login-user.test.js +148 -0
  21. package/user/use-cases/create-individual-user.js +52 -0
  22. package/user/use-cases/create-organization-user.js +39 -0
  23. package/user/use-cases/create-token-for-user-id.js +30 -0
  24. package/user/use-cases/get-user-from-bearer-token.js +50 -0
  25. package/user/use-cases/login-user.js +88 -0
  26. package/user/user-repository.js +97 -0
  27. package/user/user.js +77 -0
  28. package/handlers/routers/middleware/loadUser.js +0 -15
  29. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  30. package/integrations/create-frigg-backend.js +0 -31
  31. package/integrations/integration-user.js +0 -144
@@ -3,22 +3,29 @@ const { get } = require('../assertions');
3
3
  const Boom = require('@hapi/boom');
4
4
  const catchAsyncError = require('express-async-handler');
5
5
  const { debug } = require('../logs');
6
+
7
+
8
+ // todo: dont send moduleFactory, integrationFactory, and IntegrationHelper as a factory object, instead send them as separate
9
+ // params and import IntegrationHelper where needed.
10
+ // todo: this could be a use case class
11
+ /**
12
+ * Creates an Express router with integration and entity routes configured
13
+ * @param {Object} params - Configuration parameters for the router
14
+ * @param {express.Router} [params.router] - Optional Express router instance, creates new one if not provided
15
+ * @param {Object} params.factory - Factory object containing moduleFactory, integrationFactory, and IntegrationHelper
16
+ * @param {Object} params.factory.moduleFactory - Factory for creating and managing API modules
17
+ * @param {Object} params.factory.integrationFactory - Factory for creating and managing integrations
18
+ * @param {Object} params.factory.IntegrationHelper - Helper utilities for integration operations
19
+ * @param {import('../user/use-cases/get-user-from-bearer-token').GetUserFromBearerToken} params.getUserFromBearerToken - Use case for retrieving a user from a bearer token
20
+ * @returns {express.Router} Configured Express router with integration and entity routes
21
+ */
6
22
  function createIntegrationRouter(params) {
7
23
  const router = get(params, 'router', express());
8
24
  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);
25
+ const getUserFromBearerToken = get(params, 'getUserFromBearerToken');
19
26
 
20
- setIntegrationRoutes(router, factory, getUserId);
21
- setEntityRoutes(router, factory, getUserId);
27
+ setIntegrationRoutes(router, factory, getUserFromBearerToken);
28
+ setEntityRoutes(router, factory, getUserFromBearerToken);
22
29
  return router;
23
30
  }
24
31
 
@@ -36,33 +43,42 @@ function checkRequiredParams(params, requiredKeys) {
36
43
 
37
44
  if (missingKeys.length > 0) {
38
45
  throw Boom.badRequest(
39
- `Missing Parameter${
40
- missingKeys.length === 1 ? '' : 's'
41
- }: ${missingKeys.join(', ')} ${
42
- missingKeys.length === 1 ? 'is' : 'are'
46
+ `Missing Parameter${missingKeys.length === 1 ? '' : 's'
47
+ }: ${missingKeys.join(', ')} ${missingKeys.length === 1 ? 'is' : 'are'
43
48
  } required.`
44
49
  );
45
50
  }
46
51
  return returnDict;
47
52
  }
48
53
 
49
- function setIntegrationRoutes(router, factory, getUserId) {
54
+ /**
55
+ * Sets up integration-related routes on the provided Express router
56
+ * @param {express.Router} router - Express router instance to add routes to
57
+ * @param {Object} factory - Factory object containing moduleFactory, integrationFactory, and IntegrationHelper
58
+ * @param {Object} factory.moduleFactory - Factory for creating and managing API modules
59
+ * @param {Object} factory.integrationFactory - Factory for creating and managing integrations
60
+ * @param {Object} factory.IntegrationHelper - Helper utilities for integration operations
61
+ * @param {import('../user/use-cases/get-user-from-bearer-token').GetUserFromBearerToken} getUserFromBearerToken - Use case for retrieving a user from a bearer token
62
+ */
63
+ function setIntegrationRoutes(router, factory, getUserFromBearerToken) {
50
64
  const { moduleFactory, integrationFactory, IntegrationHelper } = factory;
51
65
  router.route('/api/integrations').get(
52
66
  catchAsyncError(async (req, res) => {
67
+ const user = await getUserFromBearerToken.execute(
68
+ req.headers.authorization
69
+ );
70
+ const userId = user.getId();
53
71
  const results = await integrationFactory.getIntegrationOptions();
54
72
  results.entities.authorized =
55
- await moduleFactory.getEntitiesForUser(getUserId(req));
73
+ await moduleFactory.getEntitiesForUser(userId);
56
74
  results.integrations =
57
- await IntegrationHelper.getIntegrationsForUserId(
58
- getUserId(req)
59
- );
75
+ await IntegrationHelper.getIntegrationsForUserId(userId);
60
76
 
61
77
  for (const integrationRecord of results.integrations) {
62
78
  const integration =
63
79
  await integrationFactory.getInstanceFromIntegrationId({
64
80
  integrationId: integrationRecord.id,
65
- userId: getUserId(req),
81
+ userId,
66
82
  });
67
83
  integrationRecord.userActions = integration.userActions;
68
84
  }
@@ -72,6 +88,10 @@ function setIntegrationRoutes(router, factory, getUserId) {
72
88
 
73
89
  router.route('/api/integrations').post(
74
90
  catchAsyncError(async (req, res) => {
91
+ const user = await getUserFromBearerToken.execute(
92
+ req.headers.authorization
93
+ );
94
+ const userId = user.getId();
75
95
  const params = checkRequiredParams(req.body, [
76
96
  'entities',
77
97
  'config',
@@ -82,7 +102,7 @@ function setIntegrationRoutes(router, factory, getUserId) {
82
102
  // create integration
83
103
  const integration = await integrationFactory.createIntegration(
84
104
  params.entities,
85
- getUserId(req),
105
+ userId,
86
106
  params.config
87
107
  );
88
108
 
@@ -102,12 +122,16 @@ function setIntegrationRoutes(router, factory, getUserId) {
102
122
 
103
123
  router.route('/api/integrations/:integrationId').patch(
104
124
  catchAsyncError(async (req, res) => {
125
+ const user = await getUserFromBearerToken.execute(
126
+ req.headers.authorization
127
+ );
128
+ const userId = user.getId();
105
129
  const params = checkRequiredParams(req.body, ['config']);
106
130
 
107
131
  const integration =
108
132
  await integrationFactory.getInstanceFromIntegrationId({
109
133
  integrationId: req.params.integrationId,
110
- userId: getUserId(req),
134
+ userId,
111
135
  });
112
136
 
113
137
  debug(
@@ -126,10 +150,14 @@ function setIntegrationRoutes(router, factory, getUserId) {
126
150
 
127
151
  router.route('/api/integrations/:integrationId').delete(
128
152
  catchAsyncError(async (req, res) => {
153
+ const user = await getUserFromBearerToken.execute(
154
+ req.headers.authorization
155
+ );
156
+ const userId = user.getId();
129
157
  const params = checkRequiredParams(req.params, ['integrationId']);
130
158
  const integration =
131
159
  await integrationFactory.getInstanceFromIntegrationId({
132
- userId: getUserId(req),
160
+ userId,
133
161
  integrationId: params.integrationId,
134
162
  });
135
163
 
@@ -138,7 +166,7 @@ function setIntegrationRoutes(router, factory, getUserId) {
138
166
  );
139
167
  await integration.send('ON_DELETE');
140
168
  await IntegrationHelper.deleteIntegrationForUserById(
141
- getUserId(req),
169
+ userId,
142
170
  params.integrationId
143
171
  );
144
172
 
@@ -148,6 +176,9 @@ function setIntegrationRoutes(router, factory, getUserId) {
148
176
 
149
177
  router.route('/api/integrations/:integrationId/config/options').get(
150
178
  catchAsyncError(async (req, res) => {
179
+ await getUserFromBearerToken.execute(
180
+ req.headers.authorization
181
+ );
151
182
  const params = checkRequiredParams(req.params, ['integrationId']);
152
183
  const integration =
153
184
  await integrationFactory.getInstanceFromIntegrationId(params);
@@ -159,6 +190,9 @@ function setIntegrationRoutes(router, factory, getUserId) {
159
190
  .route('/api/integrations/:integrationId/config/options/refresh')
160
191
  .post(
161
192
  catchAsyncError(async (req, res) => {
193
+ await getUserFromBearerToken.execute(
194
+ req.headers.authorization
195
+ );
162
196
  const params = checkRequiredParams(req.params, [
163
197
  'integrationId',
164
198
  ]);
@@ -174,6 +208,9 @@ function setIntegrationRoutes(router, factory, getUserId) {
174
208
  );
175
209
  router.route('/api/integrations/:integrationId/actions').all(
176
210
  catchAsyncError(async (req, res) => {
211
+ await getUserFromBearerToken.execute(
212
+ req.headers.authorization
213
+ );
177
214
  const params = checkRequiredParams(req.params, ['integrationId']);
178
215
  const integration =
179
216
  await integrationFactory.getInstanceFromIntegrationId(params);
@@ -185,6 +222,9 @@ function setIntegrationRoutes(router, factory, getUserId) {
185
222
  .route('/api/integrations/:integrationId/actions/:actionId/options')
186
223
  .all(
187
224
  catchAsyncError(async (req, res) => {
225
+ await getUserFromBearerToken.execute(
226
+ req.headers.authorization
227
+ );
188
228
  const params = checkRequiredParams(req.params, [
189
229
  'integrationId',
190
230
  'actionId',
@@ -209,6 +249,9 @@ function setIntegrationRoutes(router, factory, getUserId) {
209
249
  )
210
250
  .post(
211
251
  catchAsyncError(async (req, res) => {
252
+ await getUserFromBearerToken.execute(
253
+ req.headers.authorization
254
+ );
212
255
  const params = checkRequiredParams(req.params, [
213
256
  'integrationId',
214
257
  'actionId',
@@ -229,6 +272,9 @@ function setIntegrationRoutes(router, factory, getUserId) {
229
272
 
230
273
  router.route('/api/integrations/:integrationId/actions/:actionId').post(
231
274
  catchAsyncError(async (req, res) => {
275
+ await getUserFromBearerToken.execute(
276
+ req.headers.authorization
277
+ );
232
278
  const params = checkRequiredParams(req.params, [
233
279
  'integrationId',
234
280
  'actionId',
@@ -242,6 +288,9 @@ function setIntegrationRoutes(router, factory, getUserId) {
242
288
 
243
289
  router.route('/api/integrations/:integrationId').get(
244
290
  catchAsyncError(async (req, res) => {
291
+ await getUserFromBearerToken.execute(
292
+ req.headers.authorization
293
+ );
245
294
  const params = checkRequiredParams(req.params, ['integrationId']);
246
295
  const integration = await IntegrationHelper.getIntegrationById(
247
296
  params.integrationId
@@ -259,10 +308,14 @@ function setIntegrationRoutes(router, factory, getUserId) {
259
308
 
260
309
  router.route('/api/integrations/:integrationId/test-auth').get(
261
310
  catchAsyncError(async (req, res) => {
311
+ const user = await getUserFromBearerToken.execute(
312
+ req.headers.authorization
313
+ );
314
+ const userId = user.getId();
262
315
  const params = checkRequiredParams(req.params, ['integrationId']);
263
316
  const instance =
264
317
  await integrationFactory.getInstanceFromIntegrationId({
265
- userId: getUserId(req),
318
+ userId,
266
319
  integrationId: params.integrationId,
267
320
  });
268
321
 
@@ -286,9 +339,16 @@ function setIntegrationRoutes(router, factory, getUserId) {
286
339
  );
287
340
  }
288
341
 
289
- function setEntityRoutes(router, factory, getUserId) {
342
+
343
+ /**
344
+ * Sets up entity-related routes for the integration router
345
+ * @param {Object} router - Express router instance
346
+ * @param {Object} factory - Factory object containing moduleFactory and IntegrationHelper
347
+ * @param {import('../user/use-cases/get-user-from-bearer-token').GetUserFromBearerToken} getUserFromBearerToken - Use case for retrieving a user from a bearer token
348
+ */
349
+ function setEntityRoutes(router, factory, getUserFromBearerToken) {
290
350
  const { moduleFactory, IntegrationHelper } = factory;
291
- const getModuleInstance = async (req, entityType) => {
351
+ const getModuleInstance = async (userId, entityType) => {
292
352
  if (!moduleFactory.checkIsValidType(entityType)) {
293
353
  throw Boom.badRequest(
294
354
  `Error: Invalid entity type of ${entityType}, options are ${moduleFactory.moduleTypes.join(
@@ -298,14 +358,18 @@ function setEntityRoutes(router, factory, getUserId) {
298
358
  }
299
359
  return await moduleFactory.getInstanceFromTypeName(
300
360
  entityType,
301
- getUserId(req)
361
+ userId
302
362
  );
303
363
  };
304
364
 
305
365
  router.route('/api/authorize').get(
306
366
  catchAsyncError(async (req, res) => {
367
+ const user = await getUserFromBearerToken.execute(
368
+ req.headers.authorization
369
+ );
370
+ const userId = user.getId();
307
371
  const params = checkRequiredParams(req.query, ['entityType']);
308
- const module = await getModuleInstance(req, params.entityType);
372
+ const module = await getModuleInstance(userId, params.entityType);
309
373
  const areRequirementsValid =
310
374
  module.validateAuthorizationRequirements();
311
375
  if (!areRequirementsValid) {
@@ -320,15 +384,19 @@ function setEntityRoutes(router, factory, getUserId) {
320
384
 
321
385
  router.route('/api/authorize').post(
322
386
  catchAsyncError(async (req, res) => {
387
+ const user = await getUserFromBearerToken.execute(
388
+ req.headers.authorization
389
+ );
390
+ const userId = user.getId();
323
391
  const params = checkRequiredParams(req.body, [
324
392
  'entityType',
325
393
  'data',
326
394
  ]);
327
- const module = await getModuleInstance(req, params.entityType);
395
+ const module = await getModuleInstance(userId, params.entityType);
328
396
 
329
397
  res.json(
330
398
  await module.processAuthorizationCallback({
331
- userId: getUserId(req),
399
+ userId,
332
400
  data: params.data,
333
401
  })
334
402
  );
@@ -337,6 +405,10 @@ function setEntityRoutes(router, factory, getUserId) {
337
405
 
338
406
  router.route('/api/entity').post(
339
407
  catchAsyncError(async (req, res) => {
408
+ const user = await getUserFromBearerToken.execute(
409
+ req.headers.authorization
410
+ );
411
+ const userId = user.getId();
340
412
  const params = checkRequiredParams(req.body, [
341
413
  'entityType',
342
414
  'data',
@@ -352,12 +424,12 @@ function setEntityRoutes(router, factory, getUserId) {
352
424
  throw Boom.badRequest('Invalid credential ID');
353
425
  }
354
426
 
355
- const module = await getModuleInstance(req, params.entityType);
427
+ const module = await getModuleInstance(userId, params.entityType);
356
428
  const entityDetails = await module.getEntityDetails(
357
429
  module.api,
358
430
  null,
359
431
  null,
360
- getUserId(req)
432
+ userId
361
433
  );
362
434
 
363
435
  res.json(await module.findOrCreateEntity(entityDetails));
@@ -366,17 +438,21 @@ function setEntityRoutes(router, factory, getUserId) {
366
438
 
367
439
  router.route('/api/entity/options/:credentialId').get(
368
440
  catchAsyncError(async (req, res) => {
441
+ const user = await getUserFromBearerToken.execute(
442
+ req.headers.authorization
443
+ );
444
+ const userId = user.getId();
369
445
  // TODO May want to pass along the user ID as well so credential ID's can't be fished???
370
446
  // TODO **flagging this for review** -MW
371
447
  const credential = await IntegrationHelper.getCredentialById(
372
448
  req.params.credentialId
373
449
  );
374
- if (credential.user._id.toString() !== getUserId(req)) {
450
+ if (credential.user._id.toString() !== userId) {
375
451
  throw Boom.forbidden('Credential does not belong to user');
376
452
  }
377
453
 
378
454
  const params = checkRequiredParams(req.query, ['entityType']);
379
- const module = await getModuleInstance(req, params.entityType);
455
+ const module = await getModuleInstance(userId, params.entityType);
380
456
 
381
457
  res.json(await module.getEntityOptions());
382
458
  })
@@ -384,10 +460,14 @@ function setEntityRoutes(router, factory, getUserId) {
384
460
 
385
461
  router.route('/api/entities/:entityId/test-auth').get(
386
462
  catchAsyncError(async (req, res) => {
463
+ const user = await getUserFromBearerToken.execute(
464
+ req.headers.authorization
465
+ );
466
+ const userId = user.getId();
387
467
  const params = checkRequiredParams(req.params, ['entityId']);
388
468
  const module = await moduleFactory.getModuleInstanceFromEntityId(
389
469
  params.entityId,
390
- getUserId(req)
470
+ userId
391
471
  );
392
472
 
393
473
  if (!module) {
@@ -415,10 +495,14 @@ function setEntityRoutes(router, factory, getUserId) {
415
495
 
416
496
  router.route('/api/entities/:entityId').get(
417
497
  catchAsyncError(async (req, res) => {
498
+ const user = await getUserFromBearerToken.execute(
499
+ req.headers.authorization
500
+ );
501
+ const userId = user.getId();
418
502
  const params = checkRequiredParams(req.params, ['entityId']);
419
503
  const module = await moduleFactory.getModuleInstanceFromEntityId(
420
504
  params.entityId,
421
- getUserId(req)
505
+ userId
422
506
  );
423
507
 
424
508
  if (!module) {
@@ -431,13 +515,16 @@ function setEntityRoutes(router, factory, getUserId) {
431
515
 
432
516
  router.route('/api/entities/:entityId/options').post(
433
517
  catchAsyncError(async (req, res) => {
518
+ const user = await getUserFromBearerToken.execute(
519
+ req.headers.authorization
520
+ );
521
+ const userId = user.getId();
434
522
  const params = checkRequiredParams(req.params, [
435
523
  'entityId',
436
- getUserId(req),
437
524
  ]);
438
525
  const module = await moduleFactory.getModuleInstanceFromEntityId(
439
526
  params.entityId,
440
- getUserId(req)
527
+ userId
441
528
  );
442
529
 
443
530
  if (!module) {
@@ -450,13 +537,16 @@ function setEntityRoutes(router, factory, getUserId) {
450
537
 
451
538
  router.route('/api/entities/:entityId/options/refresh').post(
452
539
  catchAsyncError(async (req, res) => {
540
+ const user = await getUserFromBearerToken.execute(
541
+ req.headers.authorization
542
+ );
543
+ const userId = user.getId();
453
544
  const params = checkRequiredParams(req.params, [
454
545
  'entityId',
455
- getUserId(req),
456
546
  ]);
457
547
  const module = await moduleFactory.getModuleInstanceFromEntityId(
458
548
  params.entityId,
459
- getUserId(req)
549
+ userId
460
550
  );
461
551
 
462
552
  if (!module) {
@@ -56,7 +56,7 @@ class Auther extends Delegate {
56
56
  } else {
57
57
  if (
58
58
  definition.API.requesterType ===
59
- ModuleConstants.authType.oauth2 &&
59
+ ModuleConstants.authType.oauth2 &&
60
60
  !definition.requiredAuthMethods.getToken
61
61
  ) {
62
62
  throw new Error(
@@ -241,6 +241,7 @@ class Auther extends Delegate {
241
241
  // type: one of the types defined in modules/Constants.js
242
242
  // data: ["required", "fields", "we", "may", "need"]
243
243
  // }
244
+ console.log(this.api);
244
245
  return this.api.getAuthorizationRequirements();
245
246
  }
246
247
 
@@ -326,7 +327,7 @@ class Auther extends Delegate {
326
327
  if (search.length > 1) {
327
328
  throw new Error(
328
329
  'Multiple entities found with the same identifiers: ' +
329
- JSON.stringify(identifiers)
330
+ JSON.stringify(identifiers)
330
331
  );
331
332
  } else if (search.length === 0) {
332
333
  this.entity = await this.EntityModel.create({
@@ -1,5 +1,5 @@
1
- const { get } = require('../../assertions');
2
- const { OAuth2Requester } = require('../../module-plugin');
1
+ const { get } = require('../../../assertions');
2
+ const { OAuth2Requester } = require('../..');
3
3
 
4
4
  class Api extends OAuth2Requester {
5
5
  constructor(params) {
@@ -23,7 +23,12 @@ class Api extends OAuth2Requester {
23
23
  return this.authorizationUri;
24
24
  }
25
25
 
26
-
26
+ getAuthorizationRequirements() {
27
+ return {
28
+ url: this.getAuthUri(),
29
+ type: 'oauth2',
30
+ };
31
+ }
27
32
  }
28
33
 
29
34
  module.exports = { Api };
@@ -1,19 +1,23 @@
1
1
  require('dotenv').config();
2
- const {Api} = require('./api');
3
- const {get} = require('../../assertions');
4
- const config = {name: 'anapi'}
2
+ const { Api } = require('./api');
3
+ const { get } = require('../../../assertions');
4
+ const config = { name: 'anapi' }
5
5
 
6
6
  const Definition = {
7
7
  API: Api,
8
- getName: function() {return config.name},
8
+ getAuthorizationRequirements: () => ({
9
+ url: 'http://localhost:3000/redirect/anapi',
10
+ type: 'oauth2',
11
+ }),
12
+ getName: function () { return config.name },
9
13
  moduleName: config.name,
10
14
  modelName: 'AnApi',
11
15
  requiredAuthMethods: {
12
- getToken: async function(api, params){
16
+ getToken: async function (api, params) {
13
17
  const code = get(params.data, 'code');
14
18
  return api.getTokenFromCode(code);
15
19
  },
16
- getEntityDetails: async function(api, callbackParams, tokenResponse, userId) {
20
+ getEntityDetails: async function (api, callbackParams, tokenResponse, userId) {
17
21
  const userDetails = await api.getUserDetails();
18
22
  return {
19
23
  identifiers: { externalId: userDetails.portalId, user: userId },
@@ -26,14 +30,14 @@ const Definition = {
26
30
  ],
27
31
  entity: [],
28
32
  },
29
- getCredentialDetails: async function(api, userId) {
33
+ getCredentialDetails: async function (api, userId) {
30
34
  const userDetails = await api.getUserDetails();
31
35
  return {
32
36
  identifiers: { externalId: userDetails.portalId, user: userId },
33
37
  details: {}
34
38
  };
35
39
  },
36
- testAuthRequest: async function(api){
40
+ testAuthRequest: async function (api) {
37
41
  return api.getUserDetails()
38
42
  },
39
43
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/core",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.393.5a4db58.0",
4
+ "version": "2.0.0--canary.395.d07514c.0",
5
5
  "dependencies": {
6
6
  "@hapi/boom": "^10.0.1",
7
7
  "aws-sdk": "^2.1200.0",
@@ -22,9 +22,9 @@
22
22
  "uuid": "^9.0.1"
23
23
  },
24
24
  "devDependencies": {
25
- "@friggframework/eslint-config": "2.0.0--canary.393.5a4db58.0",
26
- "@friggframework/prettier-config": "2.0.0--canary.393.5a4db58.0",
27
- "@friggframework/test": "2.0.0--canary.393.5a4db58.0",
25
+ "@friggframework/eslint-config": "2.0.0--canary.395.d07514c.0",
26
+ "@friggframework/prettier-config": "2.0.0--canary.395.d07514c.0",
27
+ "@friggframework/test": "2.0.0--canary.395.d07514c.0",
28
28
  "@types/lodash": "4.17.15",
29
29
  "@typescript-eslint/eslint-plugin": "^8.0.0",
30
30
  "chai": "^4.3.6",
@@ -53,5 +53,5 @@
53
53
  },
54
54
  "homepage": "https://github.com/friggframework/frigg#readme",
55
55
  "description": "",
56
- "gitHead": "5a4db5802fd0ba3ae88a79981d1a9ba7fb2070d1"
56
+ "gitHead": "d07514cc9f891cbe6a53bea70322bf4c613b3058"
57
57
  }
@@ -0,0 +1,115 @@
1
+ const Boom = require('@hapi/boom');
2
+ const { User } = require('../../user');
3
+
4
+ class TestUserRepository {
5
+ constructor({ userConfig }) {
6
+ this.individualUsers = new Map();
7
+ this.organizationUsers = new Map();
8
+ this.tokens = new Map();
9
+ this.userConfig = userConfig;
10
+ }
11
+
12
+ async getSessionToken(token) {
13
+ return this.tokens.get(token);
14
+ }
15
+
16
+ async findOrganizationUserById(userId) {
17
+ const orgUserDoc = this.organizationUsers.get(userId);
18
+ if (!orgUserDoc) {
19
+ throw Boom.unauthorized('Organization User Not Found');
20
+ }
21
+ return new User(null, orgUserDoc, this.userConfig.usePassword, this.userConfig.primary, this.userConfig.individualUserRequired, this.userConfig.organizationUserRequired);
22
+ }
23
+
24
+ async findIndividualUserById(userId) {
25
+ const individualUserDoc = this.individualUsers.get(userId);
26
+ if (!individualUserDoc) {
27
+ throw Boom.unauthorized('Individual User Not Found');
28
+ }
29
+ return new User(individualUserDoc, null, this.userConfig.usePassword, this.userConfig.primary, this.userConfig.individualUserRequired, this.userConfig.organizationUserRequired);
30
+ }
31
+
32
+ async createToken(userId, rawToken, minutes = 120) {
33
+ const token = `token-for-${userId}-for-${minutes}-mins`;
34
+ this.tokens.set(token, { user: userId, rawToken });
35
+ return token;
36
+ }
37
+
38
+ async createIndividualUser(params) {
39
+ const individualUserData = { id: `individual-${Date.now()}`, ...params };
40
+ this.individualUsers.set(individualUserData.id, individualUserData);
41
+ return new User(
42
+ individualUserData,
43
+ null,
44
+ this.userConfig.usePassword,
45
+ this.userConfig.primary,
46
+ this.userConfig.individualUserRequired,
47
+ this.userConfig.organizationUserRequired
48
+ );
49
+ }
50
+
51
+ async createOrganizationUser(params) {
52
+ const orgUserData = { ...params, id: `org-${Date.now()}` };
53
+ this.organizationUsers.set(orgUserData.id, orgUserData);
54
+ return new User(
55
+ null,
56
+ orgUserData,
57
+ this.userConfig.usePassword,
58
+ this.userConfig.primary,
59
+ this.userConfig.individualUserRequired,
60
+ this.userConfig.organizationUserRequired
61
+ );
62
+ }
63
+
64
+ async findIndividualUserByUsername(username) {
65
+ for (const userDoc of this.individualUsers.values()) {
66
+ if (userDoc.username === username) {
67
+ return new User(
68
+ userDoc,
69
+ null,
70
+ this.userConfig.usePassword,
71
+ this.userConfig.primary,
72
+ this.userConfig.individualUserRequired,
73
+ this.userConfig.organizationUserRequired
74
+ );
75
+ }
76
+ }
77
+ throw Boom.unauthorized('user not found');
78
+ }
79
+
80
+ async findIndividualUserByAppUserId(appUserId) {
81
+ if (!appUserId) throw Boom.unauthorized('user not found');
82
+ for (const userDoc of this.individualUsers.values()) {
83
+ if (userDoc.appUserId === appUserId) {
84
+ return new User(
85
+ userDoc,
86
+ null,
87
+ this.userConfig.usePassword,
88
+ this.userConfig.primary,
89
+ this.userConfig.individualUserRequired,
90
+ this.userConfig.organizationUserRequired
91
+ );
92
+ }
93
+ }
94
+ throw Boom.unauthorized('user not found');
95
+ }
96
+
97
+ async findOrganizationUserByAppOrgId(appOrgId) {
98
+ if (!appOrgId) throw Boom.unauthorized('user not found');
99
+ for (const userDoc of this.organizationUsers.values()) {
100
+ if (userDoc.appOrgId === appOrgId) {
101
+ return new User(
102
+ null,
103
+ userDoc,
104
+ this.userConfig.usePassword,
105
+ this.userConfig.primary,
106
+ this.userConfig.individualUserRequired,
107
+ this.userConfig.organizationUserRequired
108
+ );
109
+ }
110
+ }
111
+ throw Boom.unauthorized('user not found');
112
+ }
113
+ }
114
+
115
+ module.exports = { TestUserRepository };