@friggframework/core 2.0.0--canary.405.1f6792c.0 → 2.0.0--canary.396.6862738.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 (59) hide show
  1. package/credential/credential-repository.js +9 -0
  2. package/credential/use-cases/get-credential-for-user.js +21 -0
  3. package/encrypt/encrypt.js +27 -4
  4. package/handlers/app-definition-loader.js +38 -0
  5. package/handlers/app-handler-helpers.js +0 -3
  6. package/handlers/backend-utils.js +29 -34
  7. package/handlers/routers/auth.js +14 -11
  8. package/handlers/routers/integration-defined-routers.js +8 -5
  9. package/handlers/routers/user.js +25 -5
  10. package/handlers/workers/integration-defined-workers.js +6 -3
  11. package/index.js +0 -11
  12. package/integrations/index.js +0 -5
  13. package/integrations/integration-base.js +10 -7
  14. package/integrations/integration-repository.js +44 -0
  15. package/integrations/integration-router.js +230 -132
  16. package/integrations/integration.js +233 -0
  17. package/integrations/options.js +1 -1
  18. package/integrations/use-cases/create-integration.js +58 -0
  19. package/integrations/use-cases/delete-integration-for-user.js +53 -0
  20. package/integrations/use-cases/get-integration-for-user.js +63 -0
  21. package/integrations/use-cases/get-integration-instance.js +73 -0
  22. package/integrations/use-cases/get-integrations-for-user.js +64 -0
  23. package/integrations/use-cases/index.js +11 -0
  24. package/integrations/use-cases/update-integration.js +81 -0
  25. package/integrations/utils/map-integration-dto.js +37 -0
  26. package/module-plugin/index.js +0 -4
  27. package/module-plugin/module-factory.js +13 -32
  28. package/module-plugin/module-repository.js +70 -0
  29. package/module-plugin/module-service.js +50 -0
  30. package/module-plugin/{auther.js → module.js} +109 -173
  31. package/module-plugin/test/mock-api/api.js +8 -3
  32. package/module-plugin/test/mock-api/definition.js +12 -8
  33. package/module-plugin/use-cases/get-entities-for-user.js +32 -0
  34. package/module-plugin/utils/map-module-dto.js +18 -0
  35. package/package.json +5 -5
  36. package/types/integrations/index.d.ts +2 -6
  37. package/types/module-plugin/index.d.ts +4 -21
  38. package/user/tests/doubles/test-user-repository.js +72 -0
  39. package/user/tests/use-cases/create-individual-user.test.js +24 -0
  40. package/user/tests/use-cases/create-organization-user.test.js +28 -0
  41. package/user/tests/use-cases/create-token-for-user-id.test.js +19 -0
  42. package/user/tests/use-cases/get-user-from-bearer-token.test.js +64 -0
  43. package/user/tests/use-cases/login-user.test.js +140 -0
  44. package/user/use-cases/create-individual-user.js +61 -0
  45. package/user/use-cases/create-organization-user.js +47 -0
  46. package/user/use-cases/create-token-for-user-id.js +30 -0
  47. package/user/use-cases/get-user-from-bearer-token.js +77 -0
  48. package/user/use-cases/login-user.js +122 -0
  49. package/user/user-repository.js +62 -0
  50. package/user/user.js +77 -0
  51. package/handlers/routers/HEALTHCHECK.md +0 -240
  52. package/handlers/routers/health.js +0 -459
  53. package/handlers/routers/health.test.js +0 -203
  54. package/handlers/routers/middleware/loadUser.js +0 -15
  55. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  56. package/integrations/create-frigg-backend.js +0 -31
  57. package/integrations/integration-factory.js +0 -251
  58. package/integrations/integration-user.js +0 -144
  59. package/module-plugin/entity-manager.js +0 -70
@@ -1,459 +0,0 @@
1
- const { Router } = require('express');
2
- const mongoose = require('mongoose');
3
- const https = require('https');
4
- const http = require('http');
5
- const { moduleFactory, integrationFactory } = require('./../backend-utils');
6
- const { createAppHandler } = require('./../app-handler-helpers');
7
-
8
- const router = Router();
9
-
10
- const validateApiKey = (req, res, next) => {
11
- const apiKey = req.headers['x-api-key'];
12
-
13
- if (req.path === '/health') {
14
- return next();
15
- }
16
-
17
- if (!apiKey || apiKey !== process.env.HEALTH_API_KEY) {
18
- return res.status(401).json({
19
- status: 'error',
20
- message: 'Unauthorized'
21
- });
22
- }
23
-
24
- next();
25
- };
26
-
27
- router.use(validateApiKey);
28
-
29
- const checkExternalAPI = (url, timeout = 5000) => {
30
- return new Promise((resolve) => {
31
- const protocol = url.startsWith('https:') ? https : http;
32
- const startTime = Date.now();
33
-
34
- try {
35
- const request = protocol.get(url, { timeout }, (res) => {
36
- const responseTime = Date.now() - startTime;
37
- resolve({
38
- status: 'healthy',
39
- statusCode: res.statusCode,
40
- responseTime,
41
- reachable: res.statusCode < 500
42
- });
43
- });
44
-
45
- request.on('error', (error) => {
46
- resolve({
47
- status: 'unhealthy',
48
- error: error.message,
49
- responseTime: Date.now() - startTime,
50
- reachable: false
51
- });
52
- });
53
-
54
- request.on('timeout', () => {
55
- request.destroy();
56
- resolve({
57
- status: 'timeout',
58
- error: 'Request timeout',
59
- responseTime: timeout,
60
- reachable: false
61
- });
62
- });
63
- } catch (error) {
64
- resolve({
65
- status: 'error',
66
- error: error.message,
67
- responseTime: Date.now() - startTime,
68
- reachable: false
69
- });
70
- }
71
- });
72
- };
73
-
74
- const getDatabaseState = () => {
75
- const stateMap = {
76
- 0: 'disconnected',
77
- 1: 'connected',
78
- 2: 'connecting',
79
- 3: 'disconnecting'
80
- };
81
- const readyState = mongoose.connection.readyState;
82
-
83
- return {
84
- readyState,
85
- stateName: stateMap[readyState],
86
- isConnected: readyState === 1
87
- };
88
- };
89
-
90
- const checkDatabaseHealth = async () => {
91
- const { stateName, isConnected } = getDatabaseState();
92
- const result = {
93
- status: isConnected ? 'healthy' : 'unhealthy',
94
- state: stateName
95
- };
96
-
97
- if (isConnected) {
98
- const pingStart = Date.now();
99
- await mongoose.connection.db.admin().ping({ maxTimeMS: 2000 });
100
- result.responseTime = Date.now() - pingStart;
101
- }
102
-
103
- return result;
104
- };
105
-
106
- const getEncryptionConfiguration = () => {
107
- const { STAGE, BYPASS_ENCRYPTION_STAGE, KMS_KEY_ARN, AES_KEY_ID } = process.env;
108
-
109
- const defaultBypassStages = ['dev', 'test', 'local'];
110
- const useEnv = BYPASS_ENCRYPTION_STAGE !== undefined;
111
- const bypassStages = useEnv
112
- ? BYPASS_ENCRYPTION_STAGE.split(',').map((s) => s.trim())
113
- : defaultBypassStages;
114
-
115
- const isBypassed = bypassStages.includes(STAGE);
116
- const hasAES = AES_KEY_ID && AES_KEY_ID.trim() !== '';
117
- const hasKMS = KMS_KEY_ARN && KMS_KEY_ARN.trim() !== '' && !hasAES;
118
- const mode = hasAES ? 'aes' : hasKMS ? 'kms' : 'none';
119
-
120
- return {
121
- stage: STAGE || null,
122
- isBypassed,
123
- hasAES,
124
- hasKMS,
125
- mode,
126
- kmsKeyArn: KMS_KEY_ARN || '(not set)',
127
- aesKeyId: AES_KEY_ID || '(not set)'
128
- };
129
- };
130
-
131
- const createTestEncryptionModel = () => {
132
- const { Encrypt } = require('./../../encrypt');
133
-
134
- const testSchema = new mongoose.Schema({
135
- testSecret: { type: String, lhEncrypt: true },
136
- normalField: { type: String },
137
- nestedSecret: {
138
- value: { type: String, lhEncrypt: true }
139
- }
140
- }, { timestamps: false });
141
-
142
- testSchema.plugin(Encrypt);
143
-
144
- return mongoose.models.TestEncryption ||
145
- mongoose.model('TestEncryption', testSchema);
146
- };
147
-
148
- const createTestDocument = async (TestModel) => {
149
- const testData = {
150
- testSecret: 'This is a secret value that should be encrypted',
151
- normalField: 'This is a normal field that should not be encrypted',
152
- nestedSecret: {
153
- value: 'This is a nested secret that should be encrypted'
154
- }
155
- };
156
-
157
- const testDoc = new TestModel(testData);
158
- await testDoc.save();
159
-
160
- return { testDoc, testData };
161
- };
162
-
163
- const verifyDecryption = (retrievedDoc, originalData) => {
164
- return retrievedDoc &&
165
- retrievedDoc.testSecret === originalData.testSecret &&
166
- retrievedDoc.normalField === originalData.normalField &&
167
- retrievedDoc.nestedSecret?.value === originalData.nestedSecret.value;
168
- };
169
-
170
- const verifyEncryptionInDatabase = async (testDoc, originalData, TestModel) => {
171
- const collectionName = TestModel.collection.name;
172
- const rawDoc = await mongoose.connection.db
173
- .collection(collectionName)
174
- .findOne({ _id: testDoc._id });
175
-
176
- const secretIsEncrypted = rawDoc &&
177
- typeof rawDoc.testSecret === 'string' &&
178
- rawDoc.testSecret.includes(':') &&
179
- rawDoc.testSecret !== originalData.testSecret;
180
-
181
- const nestedIsEncrypted = rawDoc?.nestedSecret?.value &&
182
- typeof rawDoc.nestedSecret.value === 'string' &&
183
- rawDoc.nestedSecret.value.includes(':') &&
184
- rawDoc.nestedSecret.value !== originalData.nestedSecret.value;
185
-
186
- const normalNotEncrypted = rawDoc &&
187
- rawDoc.normalField === originalData.normalField;
188
-
189
- return {
190
- secretIsEncrypted,
191
- nestedIsEncrypted,
192
- normalNotEncrypted
193
- };
194
- };
195
-
196
- const evaluateEncryptionTestResults = (decryptionWorks, encryptionResults) => {
197
- const { secretIsEncrypted, nestedIsEncrypted, normalNotEncrypted } = encryptionResults;
198
-
199
- if (decryptionWorks && secretIsEncrypted && nestedIsEncrypted && normalNotEncrypted) {
200
- return {
201
- status: 'enabled',
202
- testResult: 'Encryption and decryption verified successfully'
203
- };
204
- }
205
-
206
- if (decryptionWorks && (!secretIsEncrypted || !nestedIsEncrypted)) {
207
- return {
208
- status: 'unhealthy',
209
- testResult: 'Fields are not being encrypted in database'
210
- };
211
- }
212
-
213
- if (decryptionWorks && !normalNotEncrypted) {
214
- return {
215
- status: 'unhealthy',
216
- testResult: 'Normal fields are being incorrectly encrypted'
217
- };
218
- }
219
-
220
- return {
221
- status: 'unhealthy',
222
- testResult: 'Decryption failed or data mismatch'
223
- };
224
- };
225
-
226
- const testEncryption = async () => {
227
- const TestModel = createTestEncryptionModel();
228
- const { testDoc, testData } = await createTestDocument(TestModel);
229
-
230
- try {
231
- const retrievedDoc = await TestModel.findById(testDoc._id);
232
- const decryptionWorks = verifyDecryption(retrievedDoc, testData);
233
- const encryptionResults = await verifyEncryptionInDatabase(testDoc, testData, TestModel);
234
-
235
- const evaluation = evaluateEncryptionTestResults(decryptionWorks, encryptionResults);
236
-
237
- return {
238
- ...evaluation,
239
- encryptionWorks: decryptionWorks
240
- };
241
- } finally {
242
- await TestModel.deleteOne({ _id: testDoc._id });
243
- }
244
- };
245
-
246
- const checkEncryptionHealth = async () => {
247
- const config = getEncryptionConfiguration();
248
-
249
- if (config.isBypassed || config.mode === 'none') {
250
- const testResult = config.isBypassed
251
- ? 'Encryption bypassed for this stage'
252
- : 'No encryption keys configured';
253
-
254
- return {
255
- status: 'disabled',
256
- mode: config.mode,
257
- bypassed: config.isBypassed,
258
- stage: config.stage,
259
- testResult,
260
- encryptionWorks: false,
261
- debug: {
262
- KMS_KEY_ARN: config.kmsKeyArn,
263
- AES_KEY_ID: config.aesKeyId,
264
- hasKMS: config.hasKMS,
265
- hasAES: config.hasAES
266
- }
267
- };
268
- }
269
-
270
- try {
271
- const testResults = await testEncryption();
272
-
273
- return {
274
- ...testResults,
275
- mode: config.mode,
276
- bypassed: config.isBypassed,
277
- stage: config.stage,
278
- debug: {
279
- KMS_KEY_ARN: config.kmsKeyArn,
280
- AES_KEY_ID: config.aesKeyId,
281
- hasKMS: config.hasKMS,
282
- hasAES: config.hasAES
283
- }
284
- };
285
- } catch (error) {
286
- return {
287
- status: 'unhealthy',
288
- mode: config.mode,
289
- bypassed: config.isBypassed,
290
- stage: config.stage,
291
- testResult: `Encryption test failed: ${error.message}`,
292
- encryptionWorks: false,
293
- debug: {
294
- KMS_KEY_ARN: config.kmsKeyArn,
295
- AES_KEY_ID: config.aesKeyId,
296
- hasKMS: config.hasKMS,
297
- hasAES: config.hasAES
298
- }
299
- };
300
- }
301
- };
302
-
303
- const checkExternalAPIs = async () => {
304
- const apis = [
305
- { name: 'github', url: 'https://api.github.com/status' },
306
- { name: 'npm', url: 'https://registry.npmjs.org' }
307
- ];
308
-
309
- const results = await Promise.all(
310
- apis.map(api =>
311
- checkExternalAPI(api.url).then(result => ({ name: api.name, ...result }))
312
- )
313
- );
314
-
315
- const apiStatuses = {};
316
- let allReachable = true;
317
-
318
- results.forEach(({ name, ...checkResult }) => {
319
- apiStatuses[name] = checkResult;
320
- if (!checkResult.reachable) {
321
- allReachable = false;
322
- }
323
- });
324
-
325
- return { apiStatuses, allReachable };
326
- };
327
-
328
- const checkIntegrations = () => {
329
- const moduleTypes = Array.isArray(moduleFactory.moduleTypes)
330
- ? moduleFactory.moduleTypes
331
- : [];
332
-
333
- const integrationTypes = Array.isArray(integrationFactory.integrationTypes)
334
- ? integrationFactory.integrationTypes
335
- : [];
336
-
337
- return {
338
- status: 'healthy',
339
- modules: {
340
- count: moduleTypes.length,
341
- available: moduleTypes,
342
- },
343
- integrations: {
344
- count: integrationTypes.length,
345
- available: integrationTypes,
346
- },
347
- };
348
- };
349
-
350
- const buildHealthCheckResponse = (startTime) => {
351
- return {
352
- service: 'frigg-core-api',
353
- status: 'healthy',
354
- timestamp: new Date().toISOString(),
355
- checks: {},
356
- calculateResponseTime: () => Date.now() - startTime
357
- };
358
- };
359
-
360
- router.get('/health', async (_req, res) => {
361
- const status = {
362
- status: 'ok',
363
- timestamp: new Date().toISOString(),
364
- service: 'frigg-core-api'
365
- };
366
-
367
- res.status(200).json(status);
368
- });
369
-
370
- router.get('/health/detailed', async (_req, res) => {
371
- const startTime = Date.now();
372
- const response = buildHealthCheckResponse(startTime);
373
-
374
- try {
375
- response.checks.database = await checkDatabaseHealth();
376
- const dbState = getDatabaseState();
377
- if (!dbState.isConnected) {
378
- response.status = 'unhealthy';
379
- }
380
- } catch (error) {
381
- response.checks.database = {
382
- status: 'unhealthy',
383
- error: error.message
384
- };
385
- response.status = 'unhealthy';
386
- }
387
-
388
- try {
389
- response.checks.encryption = await checkEncryptionHealth();
390
- if (response.checks.encryption.status === 'unhealthy') {
391
- response.status = 'unhealthy';
392
- }
393
- } catch (error) {
394
- response.checks.encryption = {
395
- status: 'unhealthy',
396
- error: error.message
397
- };
398
- response.status = 'unhealthy';
399
- }
400
-
401
- const { apiStatuses, allReachable } = await checkExternalAPIs();
402
- response.checks.externalApis = apiStatuses;
403
- if (!allReachable) {
404
- response.status = 'unhealthy';
405
- }
406
-
407
- try {
408
- response.checks.integrations = checkIntegrations();
409
- } catch (error) {
410
- response.checks.integrations = {
411
- status: 'unhealthy',
412
- error: error.message
413
- };
414
- response.status = 'unhealthy';
415
- }
416
-
417
- response.responseTime = response.calculateResponseTime();
418
- delete response.calculateResponseTime;
419
-
420
- const statusCode = response.status === 'healthy' ? 200 : 503;
421
- res.status(statusCode).json(response);
422
- });
423
-
424
- router.get('/health/live', (_req, res) => {
425
- res.status(200).json({
426
- status: 'alive',
427
- timestamp: new Date().toISOString()
428
- });
429
- });
430
-
431
- router.get('/health/ready', async (_req, res) => {
432
- const dbState = getDatabaseState();
433
- const isDbReady = dbState.isConnected;
434
-
435
- let areModulesReady = false;
436
- try {
437
- const moduleTypes = Array.isArray(moduleFactory.moduleTypes)
438
- ? moduleFactory.moduleTypes
439
- : [];
440
- areModulesReady = moduleTypes.length > 0;
441
- } catch (error) {
442
- areModulesReady = false;
443
- }
444
-
445
- const isReady = isDbReady && areModulesReady;
446
-
447
- res.status(isReady ? 200 : 503).json({
448
- ready: isReady,
449
- timestamp: new Date().toISOString(),
450
- checks: {
451
- database: isDbReady,
452
- modules: areModulesReady
453
- }
454
- });
455
- });
456
-
457
- const handler = createAppHandler('HTTP Event: Health', router);
458
-
459
- module.exports = { handler, router };
@@ -1,203 +0,0 @@
1
- process.env.HEALTH_API_KEY = 'test-api-key';
2
-
3
- jest.mock('mongoose', () => ({
4
- set: jest.fn(),
5
- connection: {
6
- readyState: 1,
7
- db: {
8
- admin: () => ({
9
- ping: jest.fn().mockResolvedValue(true)
10
- })
11
- }
12
- }
13
- }));
14
-
15
- jest.mock('./../backend-utils', () => ({
16
- moduleFactory: {
17
- moduleTypes: ['test-module', 'another-module']
18
- },
19
- integrationFactory: {
20
- integrationTypes: ['test-integration', 'another-integration']
21
- }
22
- }));
23
-
24
- jest.mock('./../app-handler-helpers', () => ({
25
- createAppHandler: jest.fn((name, router) => ({ name, router }))
26
- }));
27
-
28
- const { router } = require('./health');
29
- const mongoose = require('mongoose');
30
-
31
- const mockRequest = (path, headers = {}) => ({
32
- path,
33
- headers
34
- });
35
-
36
- const mockResponse = () => {
37
- const res = {};
38
- res.status = jest.fn().mockReturnValue(res);
39
- res.json = jest.fn().mockReturnValue(res);
40
- return res;
41
- };
42
-
43
- describe('Health Check Endpoints', () => {
44
- beforeEach(() => {
45
- mongoose.connection.readyState = 1;
46
- });
47
-
48
- describe('Middleware - validateApiKey', () => {
49
- it('should allow access to /health without authentication', async () => {
50
- expect(true).toBe(true);
51
- });
52
- });
53
-
54
- describe('GET /health', () => {
55
- it('should return basic health status', async () => {
56
- const req = mockRequest('/health');
57
- const res = mockResponse();
58
-
59
- const routeHandler = router.stack.find(layer =>
60
- layer.route && layer.route.path === '/health'
61
- ).route.stack[0].handle;
62
-
63
- await routeHandler(req, res);
64
-
65
- expect(res.status).toHaveBeenCalledWith(200);
66
- expect(res.json).toHaveBeenCalledWith({
67
- status: 'ok',
68
- timestamp: expect.any(String),
69
- service: 'frigg-core-api'
70
- });
71
- });
72
- });
73
-
74
- describe('GET /health/detailed', () => {
75
- it('should return detailed health status when healthy', async () => {
76
- const req = mockRequest('/health/detailed', { 'x-api-key': 'test-api-key' });
77
- const res = mockResponse();
78
-
79
- const originalPromiseAll = Promise.all;
80
- Promise.all = jest.fn().mockResolvedValue([
81
- { name: 'github', status: 'healthy', reachable: true, statusCode: 200, responseTime: 100 },
82
- { name: 'npm', status: 'healthy', reachable: true, statusCode: 200, responseTime: 150 }
83
- ]);
84
-
85
- const routeHandler = router.stack.find(layer =>
86
- layer.route && layer.route.path === '/health/detailed'
87
- ).route.stack[0].handle;
88
-
89
- await routeHandler(req, res);
90
-
91
- Promise.all = originalPromiseAll;
92
-
93
- expect(res.status).toHaveBeenCalledWith(200);
94
- expect(res.json).toHaveBeenCalledWith(expect.objectContaining({
95
- status: 'healthy',
96
- service: 'frigg-core-api',
97
- timestamp: expect.any(String),
98
- checks: expect.objectContaining({
99
- database: expect.objectContaining({
100
- status: 'healthy',
101
- state: 'connected'
102
- }),
103
- integrations: expect.objectContaining({
104
- status: 'healthy'
105
- })
106
- }),
107
- responseTime: expect.any(Number)
108
- }));
109
-
110
- const response = res.json.mock.calls[0][0];
111
- expect(response).not.toHaveProperty('version');
112
- expect(response).not.toHaveProperty('uptime');
113
- expect(response.checks).not.toHaveProperty('memory');
114
- expect(response.checks.database).not.toHaveProperty('type');
115
- });
116
-
117
- it('should return 503 when database is disconnected', async () => {
118
- mongoose.connection.readyState = 0;
119
-
120
- const req = mockRequest('/health/detailed', { 'x-api-key': 'test-api-key' });
121
- const res = mockResponse();
122
-
123
- const originalPromiseAll = Promise.all;
124
- Promise.all = jest.fn().mockResolvedValue([
125
- { name: 'github', status: 'healthy', reachable: true, statusCode: 200, responseTime: 100 },
126
- { name: 'npm', status: 'healthy', reachable: true, statusCode: 200, responseTime: 150 }
127
- ]);
128
-
129
- const routeHandler = router.stack.find(layer =>
130
- layer.route && layer.route.path === '/health/detailed'
131
- ).route.stack[0].handle;
132
-
133
- await routeHandler(req, res);
134
-
135
- Promise.all = originalPromiseAll;
136
-
137
- expect(res.status).toHaveBeenCalledWith(503);
138
- expect(res.json).toHaveBeenCalledWith(expect.objectContaining({
139
- status: 'unhealthy'
140
- }));
141
- });
142
- });
143
-
144
- describe('GET /health/live', () => {
145
- it('should return alive status', async () => {
146
- const req = mockRequest('/health/live', { 'x-api-key': 'test-api-key' });
147
- const res = mockResponse();
148
-
149
- const routeHandler = router.stack.find(layer =>
150
- layer.route && layer.route.path === '/health/live'
151
- ).route.stack[0].handle;
152
-
153
- routeHandler(req, res);
154
-
155
- expect(res.status).toHaveBeenCalledWith(200);
156
- expect(res.json).toHaveBeenCalledWith({
157
- status: 'alive',
158
- timestamp: expect.any(String)
159
- });
160
- });
161
- });
162
-
163
- describe('GET /health/ready', () => {
164
- it('should return ready when all checks pass', async () => {
165
- const req = mockRequest('/health/ready', { 'x-api-key': 'test-api-key' });
166
- const res = mockResponse();
167
-
168
- const routeHandler = router.stack.find(layer =>
169
- layer.route && layer.route.path === '/health/ready'
170
- ).route.stack[0].handle;
171
-
172
- await routeHandler(req, res);
173
-
174
- expect(res.status).toHaveBeenCalledWith(200);
175
- expect(res.json).toHaveBeenCalledWith({
176
- ready: true,
177
- timestamp: expect.any(String),
178
- checks: {
179
- database: true,
180
- modules: true
181
- }
182
- });
183
- });
184
-
185
- it('should return 503 when database is not connected', async () => {
186
- mongoose.connection.readyState = 0;
187
-
188
- const req = mockRequest('/health/ready', { 'x-api-key': 'test-api-key' });
189
- const res = mockResponse();
190
-
191
- const routeHandler = router.stack.find(layer =>
192
- layer.route && layer.route.path === '/health/ready'
193
- ).route.stack[0].handle;
194
-
195
- await routeHandler(req, res);
196
-
197
- expect(res.status).toHaveBeenCalledWith(503);
198
- expect(res.json).toHaveBeenCalledWith(expect.objectContaining({
199
- ready: false
200
- }));
201
- });
202
- });
203
- });
@@ -1,15 +0,0 @@
1
- const catchAsyncError = require('express-async-handler');
2
- const { User } = require('../../backend-utils');
3
-
4
- module.exports = catchAsyncError(async (req, res, next) => {
5
- const authorizationHeader = req.headers.authorization;
6
-
7
- if (authorizationHeader) {
8
- // Removes "Bearer " and trims
9
- const token = authorizationHeader.split(' ')[1].trim();
10
- // Load user for later middleware/routes to use
11
- req.user = await User.newUser({ token });
12
- }
13
-
14
- return next();
15
- });
@@ -1,12 +0,0 @@
1
- const Boom = require('@hapi/boom');
2
-
3
- // CheckLoggedIn Middleware
4
- const requireLoggedInUser = (req, res, next) => {
5
- if (!req.user || !req.user.isLoggedIn()) {
6
- throw Boom.unauthorized('Invalid Token');
7
- }
8
-
9
- next();
10
- };
11
-
12
- module.exports = { requireLoggedInUser };