@w3-commons/js-build-resources 0.0.1-security → 1.0.4

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.

Potentially problematic release.


This version of @w3-commons/js-build-resources might be problematic. Click here for more details.

Files changed (98) hide show
  1. package/package.json +9 -3
  2. package/settings-service/.eslintrc.js +4 -0
  3. package/settings-service/.node-version +1 -0
  4. package/settings-service/.prettierrc +6 -0
  5. package/settings-service/.whitesource +15 -0
  6. package/settings-service/LICENSE +4 -0
  7. package/settings-service/README.md +50 -0
  8. package/settings-service/build.yml +56 -0
  9. package/settings-service/collectCodeCoverage.js +9 -0
  10. package/settings-service/db/cassandra/Dockerfile +3 -0
  11. package/settings-service/db/cassandra/createkeyspace.dev.cql +4 -0
  12. package/settings-service/db/cassandra/createkeyspace.dev.sh +3 -0
  13. package/settings-service/db/cassandra/schema_001.cql +15 -0
  14. package/settings-service/db/cassandra/schema_002.cql +8 -0
  15. package/settings-service/db/cassandra/schema_003.cql +10 -0
  16. package/settings-service/db/cassandra/schema_004.cql +1 -0
  17. package/settings-service/db/cassandra/schema_005.cql +39 -0
  18. package/settings-service/db/cassandra/schema_006.cql +255 -0
  19. package/settings-service/db/cassandra/schema_007.cql +40 -0
  20. package/settings-service/db/cassandra/schema_008.cql +2 -0
  21. package/settings-service/db/cassandra/schema_009.cql +143 -0
  22. package/settings-service/db/cassandra/schema_010.cql +143 -0
  23. package/settings-service/db/cassandra/schema_011.cql +2 -0
  24. package/settings-service/db/cassandra/schema_012.cql +8 -0
  25. package/settings-service/jest.config.fn.js +3 -0
  26. package/settings-service/jest.config.it.js +3 -0
  27. package/settings-service/jest.config.js +14 -0
  28. package/settings-service/jest.config.unit.js +19 -0
  29. package/settings-service/jest.setup.js +11 -0
  30. package/settings-service/package-lock.json +11772 -0
  31. package/settings-service/package.json +101 -0
  32. package/settings-service/scripts/run-fn-tests.sh +3 -0
  33. package/settings-service/sonar-project.properties +3 -0
  34. package/settings-service/src/__tests__/functional/controller/ApiKeyController.fn.ts +132 -0
  35. package/settings-service/src/__tests__/functional/middleware/AuthMiddlewareNextGenSSO.fn.ts +82 -0
  36. package/settings-service/src/__tests__/functional/repo/settingsRepo.fn.ts +302 -0
  37. package/settings-service/src/__tests__/functional/unified-profile/unified-profile.fn.ts +66 -0
  38. package/settings-service/src/__tests__/integration/repo/ApiKeyRepo.it.ts +43 -0
  39. package/settings-service/src/__tests__/integration/repo/settingsRepo.it.ts +142 -0
  40. package/settings-service/src/__tests__/integration/unified-profile/unified-profile.it.ts +31 -0
  41. package/settings-service/src/__tests__/unit/ErrResponse.ts +4 -0
  42. package/settings-service/src/__tests__/unit/JWTResponse.ts +18 -0
  43. package/settings-service/src/__tests__/unit/bluepagesResponse.ts +25 -0
  44. package/settings-service/src/__tests__/unit/controller/ApiKeyController.spec.ts +217 -0
  45. package/settings-service/src/__tests__/unit/controller/AppSettingsController.spec.ts +133 -0
  46. package/settings-service/src/__tests__/unit/controller/UserSettingsController.spec.ts +328 -0
  47. package/settings-service/src/__tests__/unit/controller/getAllSettings.spec.ts +83 -0
  48. package/settings-service/src/__tests__/unit/middleware/AuthMiddlewareNextGenSSO.spec.ts +282 -0
  49. package/settings-service/src/__tests__/unit/middleware/AuthenticationMiddleware.spec.ts +494 -0
  50. package/settings-service/src/__tests__/unit/repo/ApiKeyRepo.spec.ts +194 -0
  51. package/settings-service/src/__tests__/unit/repo/getAllSettings.spec.ts +100 -0
  52. package/settings-service/src/__tests__/unit/repo/getUserSettingsRepo.spec.ts +249 -0
  53. package/settings-service/src/__tests__/unit/repo/settingsRepo.spec.ts +614 -0
  54. package/settings-service/src/__tests__/unit/unified-profile/UnifiedProfileClient.spec.ts +31 -0
  55. package/settings-service/src/__tests__/unit/unified-profile/unifiedProfileUtils.spec.ts +36 -0
  56. package/settings-service/src/__tests__/utils/test-utils.ts +41 -0
  57. package/settings-service/src/config/config.ts +190 -0
  58. package/settings-service/src/controller/ApiKeyController.ts +114 -0
  59. package/settings-service/src/controller/AppSettingsController.ts +137 -0
  60. package/settings-service/src/controller/UserSettingsController.ts +202 -0
  61. package/settings-service/src/helpers/commons.ts +69 -0
  62. package/settings-service/src/logger/logger.ts +17 -0
  63. package/settings-service/src/middleware/AuthenticationMiddleware.ts +486 -0
  64. package/settings-service/src/middleware/AuthenticationMiddlewareFactory.ts +10 -0
  65. package/settings-service/src/repo/ApiKeyRepo.ts +135 -0
  66. package/settings-service/src/repo/ApiKeyRepoFactory.ts +10 -0
  67. package/settings-service/src/repo/CassandraClient.ts +33 -0
  68. package/settings-service/src/repo/CassandraClientFactory.ts +11 -0
  69. package/settings-service/src/repo/apiKeyQueries.ts +64 -0
  70. package/settings-service/src/repo/cassandraDBHelpers.ts +119 -0
  71. package/settings-service/src/repo/settingsRepo.ts +388 -0
  72. package/settings-service/src/repo/settingsRepoFactory.ts +10 -0
  73. package/settings-service/src/repo/settingsRepoQueries.ts +62 -0
  74. package/settings-service/src/routes/apiKeyRoutes.ts +27 -0
  75. package/settings-service/src/routes/appSettingsRoutes.ts +30 -0
  76. package/settings-service/src/routes/healthCheck.ts +10 -0
  77. package/settings-service/src/routes/swagger.ts +8 -0
  78. package/settings-service/src/routes/userSettingsRoutes.ts +30 -0
  79. package/settings-service/src/server.ts +77 -0
  80. package/settings-service/src/swagger.json +732 -0
  81. package/settings-service/src/types/ApiKey.ts +19 -0
  82. package/settings-service/src/types/IRequest.ts +9 -0
  83. package/settings-service/src/types/IRequestAuthorization.ts +5 -0
  84. package/settings-service/src/types/IRouteOptions.ts +5 -0
  85. package/settings-service/src/types/QueryResultsTypes.ts +6 -0
  86. package/settings-service/src/types/UserSettingsControllerTypes.ts +5 -0
  87. package/settings-service/src/types/W3IdUser.ts +36 -0
  88. package/settings-service/src/types/settingsRepoTypes.ts +61 -0
  89. package/settings-service/src/types/unifiedProfileTypes.ts +10 -0
  90. package/settings-service/src/unified-profile/UnifiedProfileClient.ts +29 -0
  91. package/settings-service/src/unified-profile/UnifiedProfileClientFactory.ts +10 -0
  92. package/settings-service/src/unified-profile/unifiedProfileUtils.ts +22 -0
  93. package/settings-service/src/util/downloadCassandra.ts +34 -0
  94. package/settings-service/src/util/isocodeMapper.ts +22 -0
  95. package/settings-service/src/util/languages.ts +1457 -0
  96. package/settings-service/test_resources/mockApiKeyDBResult.json +8 -0
  97. package/settings-service/tsconfig.json +40 -0
  98. package/README.md +0 -5
@@ -0,0 +1,66 @@
1
+ import axios from 'axios';
2
+ import http from 'axios/lib/adapters/http';
3
+ import { ApiKeyRepoFactory } from '../../../repo/ApiKeyRepoFactory';
4
+ import { deleteApiKeyQuery } from '../../../repo/apiKeyQueries';
5
+ import { ApiKeyRepo } from '../../../repo/ApiKeyRepo';
6
+ import { SettingsRepo } from '../../../repo/settingsRepo';
7
+ import { TEST_APP_ID } from '../../utils/test-utils';
8
+ import { SettingsRepoFactory } from '../../../repo/settingsRepoFactory';
9
+ import { cassandraDBHelpers } from '../../../repo/cassandraDBHelpers';
10
+ import { downloadCassandra } from '../../../util/downloadCassandra';
11
+
12
+ axios.defaults.adapter = http;
13
+
14
+ const FAKE_USER_ID = 'TEST_USER';
15
+
16
+ // broadcast ID has a Unified Profile but no stored settings in settings-service
17
+ const TEST_BROADCAST_ID = 'C-RR67897';
18
+
19
+ async function apiKeySetup(): Promise<string> {
20
+ const apiKeyRepo: ApiKeyRepo = ApiKeyRepoFactory.accessOrCreateSingleton();
21
+ const createdApiKey = await apiKeyRepo.createApiKey(TEST_APP_ID, 'TEST_USER_ID');
22
+ return Buffer.from(`w3notifications-test:${createdApiKey}`).toString('base64');
23
+ }
24
+
25
+ let TEST_HEADER_API: any = {};
26
+
27
+ const urlprefix =
28
+ process.env.INGRESS_HOSTNAME !== undefined
29
+ ? `https://${process.env.INGRESS_HOSTNAME}`
30
+ : 'http://localhost:8000';
31
+
32
+ const settingsRepo: SettingsRepo = SettingsRepoFactory.accessOrCreateSingleton();
33
+
34
+ describe('unified-profile backup call', () => {
35
+ const TEST_RESP = { general: {} };
36
+ TEST_RESP[TEST_APP_ID] = {};
37
+
38
+ beforeAll(async () => {
39
+ await downloadCassandra();
40
+ await settingsRepo.deleteUserSettings(FAKE_USER_ID);
41
+ await settingsRepo.deleteUserSettings(TEST_BROADCAST_ID);
42
+ TEST_HEADER_API = { headers: { Authorization: `apiKey ${await apiKeySetup()}` } };
43
+ });
44
+
45
+ afterAll(async () => {
46
+ await settingsRepo.deleteUserSettings(FAKE_USER_ID);
47
+ await settingsRepo.deleteUserSettings(TEST_BROADCAST_ID);
48
+ await cassandraDBHelpers.execute(deleteApiKeyQuery, [TEST_APP_ID]);
49
+ await cassandraDBHelpers.shutdown();
50
+ });
51
+
52
+ it('returns default language when no primary language in unified profile', async () => {
53
+ const data = await axios
54
+ .get(`${urlprefix}/v1/settings/users/${FAKE_USER_ID}/apps/general`, TEST_HEADER_API)
55
+ .then((res) => res.data);
56
+ expect(data.general.primaryLanguage).toEqual('en');
57
+ });
58
+
59
+ it('returns language from Unified Profile when no primary language in settings service', async () => {
60
+ // TEST_BROADCAST_ID has a unified profile, but no settings in settings-service
61
+ const data = await axios
62
+ .get(`${urlprefix}/v1/settings/users/${TEST_BROADCAST_ID}/apps/general`, TEST_HEADER_API)
63
+ .then((res) => res.data);
64
+ expect(data.general.primaryLanguage).toEqual('en');
65
+ });
66
+ });
@@ -0,0 +1,43 @@
1
+ import { ApiKeyRepoFactory } from '../../../repo/ApiKeyRepoFactory';
2
+ import { deleteApiKeyQuery } from '../../../repo/apiKeyQueries';
3
+ import { ApiKeyRepo } from '../../../repo/ApiKeyRepo';
4
+ import { cassandraDBHelpers } from '../../../repo/cassandraDBHelpers';
5
+ import { TEST_APP_ID, TEST_USER_ID } from '../../utils/test-utils';
6
+
7
+ beforeAll(async () => {
8
+ await cassandraDBHelpers.execute(deleteApiKeyQuery, [TEST_APP_ID]);
9
+ });
10
+ afterAll(async () => {
11
+ await cassandraDBHelpers.execute(deleteApiKeyQuery, [TEST_APP_ID]);
12
+ await cassandraDBHelpers.shutdown();
13
+ });
14
+
15
+ describe('cassandra apiKey integration', () => {
16
+ let originalApiKey: string;
17
+ const apiKeyRepo: ApiKeyRepo = ApiKeyRepoFactory.accessOrCreateSingleton();
18
+
19
+ it('should create api key in database', async () => {
20
+ const res = await apiKeyRepo.createApiKey(TEST_APP_ID, TEST_USER_ID);
21
+ originalApiKey = res;
22
+
23
+ expect(res).toBeDefined();
24
+ expect(typeof res).toBe('string');
25
+ expect(res).toHaveLength(48);
26
+ });
27
+
28
+ it('should get correct apiKey from database', async () => {
29
+ const res = await apiKeyRepo.getApiKey(TEST_APP_ID);
30
+
31
+ expect(res).toBeDefined();
32
+ expect(res.key).toEqual(originalApiKey);
33
+ });
34
+
35
+ it('should update api key in database', async () => {
36
+ const res = await apiKeyRepo.updateApiKey(TEST_APP_ID, TEST_USER_ID);
37
+
38
+ expect(res).toBeDefined();
39
+ expect(res).not.toEqual(originalApiKey);
40
+ expect(typeof res).toBe('string');
41
+ expect(res).toHaveLength(48);
42
+ });
43
+ });
@@ -0,0 +1,142 @@
1
+ import axios from 'axios';
2
+ import { ApiKeyRepoFactory } from '../../../repo/ApiKeyRepoFactory';
3
+ import { deleteApiKeyQuery } from '../../../repo/apiKeyQueries';
4
+ import { ApiKeyRepo } from '../../../repo/ApiKeyRepo';
5
+ import { cassandraDBHelpers } from '../../../repo/cassandraDBHelpers';
6
+ import { SettingsRepo } from '../../../repo/settingsRepo';
7
+ import { fetchAppSettingsDataQuery, fetchUserSettingsDataQuery } from '../../../repo/settingsRepoQueries';
8
+ import { sampleAuthorization, TEST_APP_ID, TEST_USER_ID } from '../../utils/test-utils';
9
+ import { SettingsRepoFactory } from '../../../repo/settingsRepoFactory';
10
+
11
+ const TEST_SETTING = 'test';
12
+ const TEST_OPTIONS = ['dark'];
13
+ const TEST_SETTING_OPTIONS = { test: { options: TEST_OPTIONS, default: null } };
14
+
15
+ const settingsRepo: SettingsRepo = SettingsRepoFactory.accessOrCreateSingleton();
16
+
17
+ describe('cassandra integration', () => {
18
+ const TEST_RESP = {};
19
+ TEST_RESP[TEST_APP_ID] = TEST_SETTING_OPTIONS;
20
+
21
+ beforeAll(async () => {
22
+ await settingsRepo.deleteUserSettings(TEST_USER_ID);
23
+ await settingsRepo.deleteAppSettings(TEST_APP_ID, TEST_SETTING);
24
+ });
25
+
26
+ afterAll(async () => {
27
+ await settingsRepo.deleteUserSettings(TEST_USER_ID);
28
+ await settingsRepo.deleteAppSettings(TEST_APP_ID, TEST_SETTING);
29
+ });
30
+
31
+ it('updates app setting', async () => {
32
+ const res = await settingsRepo.updateAppSettings({
33
+ appId: TEST_APP_ID,
34
+ settingName: TEST_SETTING,
35
+ settingOptions: TEST_OPTIONS,
36
+ });
37
+ expect(res).toEqual(true);
38
+ });
39
+
40
+ it('reads updated app settings', async () => {
41
+ const res = await settingsRepo.getAppSettings(TEST_APP_ID, TEST_SETTING);
42
+ expect(res).toEqual(TEST_RESP[TEST_APP_ID]);
43
+ });
44
+
45
+ it('updates user data', async () => {
46
+ const res = await settingsRepo.updateUserSettings(
47
+ TEST_USER_ID,
48
+ TEST_APP_ID,
49
+ TEST_SETTING,
50
+ TEST_OPTIONS[0],
51
+ );
52
+ expect(res).toEqual(true);
53
+ });
54
+
55
+ it('reads updated user settings', async () => {
56
+ const res = await settingsRepo.getUserSettings(TEST_USER_ID, TEST_APP_ID);
57
+ expect(res[TEST_SETTING]).toEqual(TEST_OPTIONS[0]);
58
+ });
59
+
60
+ it('deletes user settings', async () => {
61
+ const res = await settingsRepo.deleteUserSettings(TEST_USER_ID);
62
+ expect(res).toEqual(true);
63
+ });
64
+
65
+ it('deletes app settings', async () => {
66
+ const res = await settingsRepo.deleteAppSettings(TEST_APP_ID, TEST_SETTING);
67
+ expect(res).toEqual(true);
68
+ });
69
+ });
70
+
71
+ describe('array value storage tests', () => {
72
+ it('reads general settings', async () => {
73
+ await cassandraDBHelpers.execute(fetchAppSettingsDataQuery, ['general']).then((results) => {
74
+ const settingsAndDefaults: Map<string, string> = new Map<string, string>();
75
+ for (const row of results.rows) {
76
+ const { setting_name } = row;
77
+ const { setting_default } = row;
78
+ settingsAndDefaults.set(setting_name, setting_default);
79
+ }
80
+ expect(settingsAndDefaults.get('primaryLanguage')).toBe('en');
81
+ expect(settingsAndDefaults.get('secondaryLanguages')).toBe(null);
82
+ expect(settingsAndDefaults.get('secondaryLocationIds')).toBe(null);
83
+ });
84
+ });
85
+ });
86
+
87
+ describe('array value storage tests', () => {
88
+ const TEST_HEADER = { headers: { Authorization: `Bearer ${JSON.stringify(sampleAuthorization)}` } };
89
+ const urlprefix =
90
+ process.env.INGRESS_HOSTNAME !== undefined
91
+ ? `https://${process.env.INGRESS_HOSTNAME}`
92
+ : 'http://localhost:8000';
93
+
94
+ async function apiKeySetup(): Promise<string> {
95
+ const apiKeyRepo: ApiKeyRepo = ApiKeyRepoFactory.accessOrCreateSingleton();
96
+ const createdApiKey = await apiKeyRepo.createApiKey(TEST_APP_ID, 'TEST_USER_ID');
97
+ return Buffer.from(`w3notifications-test:${createdApiKey}`).toString('base64');
98
+ }
99
+ let TEST_HEADER_API: any = {};
100
+
101
+ const secondaryLanguageSetting = { options: ['sk', 'en', 'fr'], setting_type: 'array' };
102
+
103
+ beforeAll(async () => {
104
+ await settingsRepo.deleteUserSettings(TEST_USER_ID);
105
+ await settingsRepo.deleteAppSettings(TEST_APP_ID, 'secondaryLanguages');
106
+ TEST_HEADER_API = { headers: { Authorization: `apiKey ${await apiKeySetup()}` } };
107
+ await axios.post(
108
+ `${urlprefix}/v1/settings/app/${TEST_APP_ID}/setting/secondaryLanguages`,
109
+ secondaryLanguageSetting,
110
+ TEST_HEADER_API,
111
+ );
112
+ });
113
+
114
+ afterAll(async () => {
115
+ await settingsRepo.deleteUserSettings(TEST_USER_ID);
116
+ await cassandraDBHelpers.execute(deleteApiKeyQuery, [TEST_APP_ID]);
117
+ await settingsRepo.deleteAppSettings(TEST_APP_ID, 'secondaryLanguages');
118
+ await cassandraDBHelpers.shutdown();
119
+ });
120
+
121
+ it('can post an array value and store as a string', async () => {
122
+ const updatedSetting = { secondaryLanguages: ['en', 'fr'] };
123
+ await axios.post(
124
+ `${urlprefix}/v1/settings/users/${TEST_USER_ID}/apps/${TEST_APP_ID}`,
125
+ updatedSetting,
126
+ TEST_HEADER,
127
+ );
128
+
129
+ await cassandraDBHelpers
130
+ .execute(fetchUserSettingsDataQuery, [TEST_USER_ID, TEST_APP_ID])
131
+ .then((results) => {
132
+ expect(results.rows[0].setting_value).toBe('en,fr');
133
+ });
134
+ });
135
+
136
+ it('can retrieve a string value and return as array', async () => {
137
+ const data = await axios
138
+ .get(`${urlprefix}/v1/settings/users/${TEST_USER_ID}/apps/${TEST_APP_ID}`, TEST_HEADER)
139
+ .then((res) => res.data);
140
+ expect(data[TEST_APP_ID].secondaryLanguages).toEqual(['en', 'fr']);
141
+ });
142
+ });
@@ -0,0 +1,31 @@
1
+ import { SettingsRepoFactory } from '../../../repo/settingsRepoFactory';
2
+ import { cassandraDBHelpers } from '../../../repo/cassandraDBHelpers';
3
+ import { SettingsRepo } from '../../../repo/settingsRepo';
4
+
5
+ const TEST_USER_ID = 'TESTUSER';
6
+
7
+ const settingsRepo: SettingsRepo = SettingsRepoFactory.accessOrCreateSingleton();
8
+
9
+ // broadcast ID has a Unified Profile but no stored settings in settings-service
10
+ const TEST_BROADCAST_ID = 'C-RR67897';
11
+
12
+ describe('unified-profile backup call', () => {
13
+ beforeEach(async () => {
14
+ await settingsRepo.deleteUserSettings(TEST_USER_ID);
15
+ await settingsRepo.deleteUserSettings(TEST_BROADCAST_ID);
16
+ });
17
+ afterAll(async () => {
18
+ await settingsRepo.deleteUserSettings(TEST_USER_ID);
19
+ await settingsRepo.deleteUserSettings(TEST_BROADCAST_ID);
20
+ await cassandraDBHelpers.shutdown();
21
+ });
22
+ it('returns default language setting if user does not have a profile', async () => {
23
+ const res = await settingsRepo.getUserSettings(TEST_USER_ID, 'general');
24
+ expect(res.primaryLanguage).toEqual('en');
25
+ });
26
+ it('returns language from unified profile if no primary language in settings-service', async () => {
27
+ // TEST_BROADCAST_ID has a unified profile, but no stored settings in settings-service
28
+ const res = await settingsRepo.getUserSettings(TEST_BROADCAST_ID, 'general');
29
+ expect(res.primaryLanguage).toEqual('en');
30
+ });
31
+ });
@@ -0,0 +1,4 @@
1
+ export interface ErrResponse {
2
+ code: number;
3
+ message: string;
4
+ }
@@ -0,0 +1,18 @@
1
+ export const jwtResponse = {
2
+ id: 'John.Doe@ibm.com',
3
+ cn: 'John Doe',
4
+ uid: 'AAABBB555',
5
+ isW3HomepageAdmin: false,
6
+ hkey: 'b342d835af74c094d868829d2099c04c1eb81351c2078265c3227559fc80959e',
7
+ iat: 1548773356,
8
+ exp: 1548816556,
9
+ };
10
+
11
+ export const jwtBadResponse = {
12
+ id: 'John.Doe@ibm.com',
13
+ cn: 'John Doe',
14
+ isW3HomepageAdmin: false,
15
+ hkey: 'b342d835af74c094d868829d2099c04c1eb81351c2078265c3227559fc80959e',
16
+ iat: 1548773356,
17
+ exp: 1548816556,
18
+ };
@@ -0,0 +1,25 @@
1
+ export const bluepagesResponse = {
2
+ userId: 'AAABBB555',
3
+ active: true,
4
+ content: {
5
+ user: {
6
+ profile: {
7
+ uid: 'AAABBB555',
8
+ id: 'AAABBB555',
9
+ email: 'John.Doe@ibm.com',
10
+ notesMailDomain: 'IBM',
11
+ nameFull: 'John Doe',
12
+ courtesyTitle: 'Mr.',
13
+ nameDisplay: 'John Doe',
14
+ notesShortName: 'AAABBB',
15
+ name: {
16
+ last: 'Doe',
17
+ first: 'John',
18
+ },
19
+ preferredIdentity: 'John.Doe@ibm.com',
20
+ callup: 'Doe, John B (JOHN)',
21
+ notes: 'John Doe/US/IBM',
22
+ },
23
+ },
24
+ },
25
+ };
@@ -0,0 +1,217 @@
1
+ import { Request, Response } from 'restify';
2
+ import { settings } from '../../../config/config';
3
+ import { fetchApiKey, postApiKey, putApiKey } from '../../../controller/ApiKeyController';
4
+ import { ApiKeyRepoImpl } from '../../../repo/ApiKeyRepo';
5
+ import {
6
+ INVALID_APP_ID,
7
+ mockApiKey,
8
+ TEST_API_KEY,
9
+ TEST_APP_ID,
10
+ TEST_USER_ID,
11
+ } from '../../utils/test-utils';
12
+
13
+ settings.settingsAppIds = ['w3notifications-test', 'general'];
14
+
15
+ afterEach(() => {
16
+ jest.resetAllMocks();
17
+ });
18
+
19
+ function test_send(code?: number | undefined, body?: any): any {
20
+ return { code, body };
21
+ }
22
+
23
+ describe('fetchApiKey', () => {
24
+ const request: Request = {} as Request;
25
+ const response: Response = {} as Response;
26
+ response.send = test_send;
27
+
28
+ it('should respond with 200 and send apiKey for valid appID', async () => {
29
+ request.params = { appID: TEST_APP_ID };
30
+
31
+ const getApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'getApiKey').mockResolvedValue(mockApiKey);
32
+
33
+ const responseObj: any = await fetchApiKey(request, response);
34
+
35
+ expect(responseObj.code).toEqual(200);
36
+ expect(responseObj.body).toEqual(mockApiKey);
37
+ expect(getApiKeySpy).toHaveBeenCalled();
38
+ });
39
+
40
+ it('should respond with 400 when no appID provided', async () => {
41
+ request.params = {};
42
+
43
+ const responseObj: any = await fetchApiKey(request, response);
44
+
45
+ expect(responseObj.code).toEqual(400);
46
+ expect(responseObj.body.message).toEqual('Missing required query params.');
47
+ });
48
+
49
+ it('should respond with 400 when appId invalid', async () => {
50
+ request.params = { appID: INVALID_APP_ID };
51
+ const getApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'createApiKey');
52
+
53
+ const responseObj: any = await fetchApiKey(request, response);
54
+
55
+ expect(responseObj.code).toEqual(400);
56
+ expect(responseObj.body.message).toEqual('Invalid appID');
57
+ expect(getApiKeySpy).not.toHaveBeenCalled();
58
+ });
59
+
60
+ it('should respond with 500 if error caught', async () => {
61
+ request.params = { appID: TEST_APP_ID };
62
+ const getApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'getApiKey').mockImplementationOnce(() => {
63
+ throw new Error('error in getApiKey');
64
+ });
65
+
66
+ const responseObj: any = await fetchApiKey(request, response);
67
+
68
+ expect(responseObj.code).toEqual(500);
69
+ expect(responseObj.body.message).toEqual('Unable to fetch Api Key');
70
+ expect(getApiKeySpy).toHaveBeenCalled();
71
+ });
72
+ });
73
+
74
+ describe('postApiKey', () => {
75
+ const request: Request = {} as Request;
76
+ const response: Response = {} as Response;
77
+ response.send = test_send;
78
+
79
+ it('should respond with 200 when key successfully created', async () => {
80
+ request.params = { appID: TEST_APP_ID };
81
+ request.username = TEST_USER_ID;
82
+ const createApiKeySpy = jest
83
+ .spyOn(ApiKeyRepoImpl.prototype, 'createApiKey')
84
+ .mockResolvedValueOnce(TEST_API_KEY);
85
+
86
+ const responseObj: any = await postApiKey(request, response);
87
+
88
+ expect(responseObj.code).toEqual(200);
89
+ expect(responseObj.body.key).toEqual(mockApiKey.key);
90
+ expect(createApiKeySpy).toHaveBeenCalled();
91
+ });
92
+
93
+ it('should respond with 400 when missing appId', async () => {
94
+ request.params = {};
95
+ request.username = TEST_USER_ID;
96
+ const createApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'createApiKey');
97
+ const responseObj: any = await postApiKey(request, response);
98
+
99
+ expect(responseObj.code).toEqual(400);
100
+ expect(responseObj.body.message).toEqual('Missing required query params.');
101
+ expect(createApiKeySpy).not.toHaveBeenCalled();
102
+ });
103
+
104
+ it('should respond with 400 when missing username', async () => {
105
+ request.params = { appID: TEST_APP_ID };
106
+ request.username = undefined;
107
+ const createApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'createApiKey');
108
+
109
+ const responseObj: any = await postApiKey(request, response);
110
+
111
+ expect(responseObj.code).toEqual(400);
112
+ expect(responseObj.body.message).toEqual('Missing request username');
113
+ expect(createApiKeySpy).not.toHaveBeenCalled();
114
+ });
115
+
116
+ it('should respond with 400 when appId invalid', async () => {
117
+ request.params = { appID: INVALID_APP_ID };
118
+ request.username = TEST_USER_ID;
119
+ const createApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'createApiKey');
120
+
121
+ const responseObj: any = await postApiKey(request, response);
122
+
123
+ expect(responseObj.code).toEqual(400);
124
+ expect(responseObj.body.message).toEqual('Invalid appID');
125
+ expect(createApiKeySpy).not.toHaveBeenCalled();
126
+ });
127
+
128
+ it('should respond with 500 if error caught', async () => {
129
+ request.params = { appID: TEST_APP_ID };
130
+ request.username = TEST_USER_ID;
131
+
132
+ const createApiKeySpy = jest
133
+ .spyOn(ApiKeyRepoImpl.prototype, 'createApiKey')
134
+ .mockImplementationOnce(() => {
135
+ throw new Error('error in createApiKey');
136
+ });
137
+
138
+ const responseObj: any = await postApiKey(request, response);
139
+
140
+ expect(responseObj.code).toEqual(500);
141
+ expect(responseObj.body.message).toEqual('Unable to create api key');
142
+ expect(createApiKeySpy).toHaveBeenCalled();
143
+ });
144
+ });
145
+
146
+ describe('putApiKey', () => {
147
+ const request: Request = {} as Request;
148
+ const response: Response = {} as Response;
149
+ response.send = test_send;
150
+
151
+ it('should respond with 200 when updating apiKey', async () => {
152
+ request.params = { appID: TEST_APP_ID };
153
+ request.username = TEST_USER_ID;
154
+
155
+ const updateApiKeySpy = jest
156
+ .spyOn(ApiKeyRepoImpl.prototype, 'updateApiKey')
157
+ .mockResolvedValueOnce(TEST_API_KEY);
158
+
159
+ const responseObj: any = await putApiKey(request, response);
160
+
161
+ expect(responseObj.code).toEqual(200);
162
+ expect(responseObj.body.key).toEqual(TEST_API_KEY);
163
+ expect(updateApiKeySpy).toHaveBeenCalled();
164
+ });
165
+
166
+ it('should respond with 400 when missing appId', async () => {
167
+ request.params = {};
168
+ request.username = TEST_USER_ID;
169
+ const updateApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'updateApiKey');
170
+ const responseObj: any = await putApiKey(request, response);
171
+
172
+ expect(responseObj.code).toEqual(400);
173
+ expect(responseObj.body.message).toEqual('Missing required query params.');
174
+ expect(updateApiKeySpy).not.toHaveBeenCalled();
175
+ });
176
+
177
+ it('should respond with 400 when missing username', async () => {
178
+ request.params = { appID: TEST_APP_ID };
179
+ request.username = undefined;
180
+ const updateApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'updateApiKey');
181
+
182
+ const responseObj: any = await putApiKey(request, response);
183
+
184
+ expect(responseObj.code).toEqual(400);
185
+ expect(responseObj.body.message).toEqual('Missing request username');
186
+ expect(updateApiKeySpy).not.toHaveBeenCalled();
187
+ });
188
+
189
+ it('should respond with 400 when appId invalid', async () => {
190
+ request.params = { appID: INVALID_APP_ID };
191
+ request.username = TEST_USER_ID;
192
+ const updateApiKeySpy = jest.spyOn(ApiKeyRepoImpl.prototype, 'updateApiKey');
193
+
194
+ const responseObj: any = await putApiKey(request, response);
195
+
196
+ expect(responseObj.code).toEqual(400);
197
+ expect(responseObj.body.message).toEqual('Invalid appID');
198
+ expect(updateApiKeySpy).not.toHaveBeenCalled();
199
+ });
200
+
201
+ it('should respond with 500 if error caught', async () => {
202
+ request.params = { appID: TEST_APP_ID };
203
+ request.username = TEST_USER_ID;
204
+
205
+ const updateApiKeySpy = jest
206
+ .spyOn(ApiKeyRepoImpl.prototype, 'updateApiKey')
207
+ .mockImplementationOnce(() => {
208
+ throw new Error('error in updateApiKey');
209
+ });
210
+
211
+ const responseObj: any = await putApiKey(request, response);
212
+
213
+ expect(responseObj.code).toEqual(500);
214
+ expect(responseObj.body.message).toEqual('Unable to update api key');
215
+ expect(updateApiKeySpy).toHaveBeenCalled();
216
+ });
217
+ });
@@ -0,0 +1,133 @@
1
+ import { Request, Response } from 'restify';
2
+ import { settings } from '../../../config/config';
3
+ import {
4
+ deleteAppSettings,
5
+ getAppSettings,
6
+ postAppSettings,
7
+ } from '../../../controller/AppSettingsController';
8
+ import { cassandraDBHelpers } from '../../../repo/cassandraDBHelpers';
9
+ import { INVALID_APP_ID, TEST_APP_ID } from '../../utils/test-utils';
10
+
11
+ settings.settingsAppIds = ['w3notifications-test', 'general'];
12
+
13
+ const SETTING_NAME = 'test';
14
+ const SETTING_OPTIONS = ['true', 'false'];
15
+
16
+ function test_send(code?: number | undefined): any {
17
+ return code;
18
+ }
19
+
20
+ describe('get settings using appID', () => {
21
+ const request: Request = {} as Request;
22
+ const response: Response = {} as Response;
23
+
24
+ request.params = { appID: TEST_APP_ID };
25
+ request.query = {};
26
+
27
+ it('should return 200 set while getting data', async () => {
28
+ const mockResultSet: any = {
29
+ rows: [],
30
+ };
31
+ cassandraDBHelpers.execute = jest.fn().mockReturnValue(
32
+ new Promise((resolve) => {
33
+ resolve(mockResultSet);
34
+ }),
35
+ );
36
+ response.send = test_send;
37
+ expect(await getAppSettings(request, response)).toEqual(200);
38
+ });
39
+ it('invalid appID should return 400 error', async () => {
40
+ request.params.appID = INVALID_APP_ID;
41
+ response.send = test_send;
42
+ expect(await getAppSettings(request, response)).toEqual(400);
43
+ });
44
+ it('internal server error should return 500 error', async () => {
45
+ request.params = undefined;
46
+ response.send = test_send;
47
+ expect(await getAppSettings(request, response)).toEqual(500);
48
+ });
49
+ });
50
+
51
+ describe('post settings', () => {
52
+ const request: Request = {} as Request;
53
+ const response: Response = {} as Response;
54
+
55
+ request.params = { appID: 'general', settingName: SETTING_NAME };
56
+ request.query = {};
57
+ request.body = { options: SETTING_OPTIONS, setting_type: null };
58
+
59
+ it('should return 200 set while posting data', async () => {
60
+ const mockResultSet: any = {
61
+ rows: [],
62
+ };
63
+ cassandraDBHelpers.execute = jest.fn().mockReturnValue(
64
+ new Promise((resolve) => {
65
+ resolve(mockResultSet);
66
+ }),
67
+ );
68
+ response.send = test_send;
69
+ expect(await postAppSettings(request, response)).toEqual(200);
70
+ });
71
+ it('json error should return 500 error', async () => {
72
+ request.body = [];
73
+ response.send = test_send;
74
+ expect(await postAppSettings(request, response)).toEqual(500);
75
+ });
76
+ it('invalid default should return 500 error', async () => {
77
+ request.body = { default: 'invalid', options: SETTING_OPTIONS };
78
+ response.send = test_send;
79
+ expect(await postAppSettings(request, response)).toEqual(500);
80
+ });
81
+ it('invalid input should return 400 error', async () => {
82
+ request.params.appID = INVALID_APP_ID;
83
+ response.send = test_send;
84
+ expect(await postAppSettings(request, response)).toEqual(400);
85
+ request.params.appID = null;
86
+ expect(await postAppSettings(request, response)).toEqual(400);
87
+ });
88
+ it('internal server error should return 500 error', async () => {
89
+ request.params = undefined;
90
+ response.send = test_send;
91
+ expect(await postAppSettings(request, response)).toEqual(500);
92
+ });
93
+ it('invalid setting_type will return 400 error', async () => {
94
+ const invalidType = 'invalid setting type';
95
+ request.body = { options: SETTING_OPTIONS, setting_type: invalidType };
96
+ response.send = test_send;
97
+ request.params = { appID: 'general', settingName: SETTING_NAME };
98
+ expect(await postAppSettings(request, response)).toEqual(400);
99
+ });
100
+ });
101
+
102
+ describe('delete settings', () => {
103
+ const request: Request = {} as Request;
104
+ const response: Response = {} as Response;
105
+
106
+ request.params = { appID: 'general', settingName: SETTING_NAME };
107
+ request.query = {};
108
+
109
+ it('should return 200 set while deleting data', async () => {
110
+ const mockResultSet: any = {
111
+ rows: [],
112
+ };
113
+ cassandraDBHelpers.execute = jest.fn().mockReturnValue(
114
+ new Promise((resolve) => {
115
+ resolve(mockResultSet);
116
+ }),
117
+ );
118
+ response.send = test_send;
119
+ expect(await deleteAppSettings(request, response)).toEqual(200);
120
+ });
121
+ it('invalid input should return 400 error', async () => {
122
+ request.params.appID = INVALID_APP_ID;
123
+ response.send = test_send;
124
+ expect(await deleteAppSettings(request, response)).toEqual(400);
125
+ request.params.appID = null;
126
+ expect(await deleteAppSettings(request, response)).toEqual(400);
127
+ });
128
+ it('internal server error should return 500 error', async () => {
129
+ request.params = undefined;
130
+ response.send = test_send;
131
+ expect(await deleteAppSettings(request, response)).toEqual(500);
132
+ });
133
+ });