@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,135 @@
1
+ import { types } from 'dse-driver';
2
+ import * as _ from 'lodash';
3
+ import { NotFoundError } from 'restify-errors';
4
+ import { settings } from '../config/config';
5
+ import { logger } from '../logger/logger';
6
+ import { ApiKey } from '../types/ApiKey';
7
+ import { createRandomToken, decrypt, encrypt } from '../helpers/commons';
8
+ import * as apiKeyQueries from './apiKeyQueries';
9
+ import { cassandraDBHelpers } from './cassandraDBHelpers';
10
+
11
+ export interface ApiKeyRepo {
12
+ getApiKey(appId: string): Promise<ApiKey>;
13
+ createApiKey(appId: string, createdBy: string): Promise<string>;
14
+ updateApiKey(appId: string, updatedBy: string): Promise<string>;
15
+ }
16
+
17
+ export class ApiKeyRepoImpl {
18
+ /**
19
+ * This method returns the API key for the provided appId stored in Cassandra DB.
20
+ *
21
+ * @param appId
22
+ */
23
+ public async getApiKey(appId: string): Promise<ApiKey> {
24
+ return cassandraDBHelpers
25
+ .execute(apiKeyQueries.selectApiKeyByAppId, apiKeyQueries.appKeyPKeyValues(_.toLower(appId)))
26
+ .then((result: types.ResultSet) => {
27
+ const row = result.first();
28
+ if (row === null) {
29
+ throw new NotFoundError(`ApiKey for the appId: ${JSON.stringify(appId)} doesn't exist.`);
30
+ }
31
+ const apiKey: Promise<ApiKey> = apiKeyQueries.rowToApiKey(JSON.parse(row['[json]']));
32
+ return apiKey;
33
+ })
34
+ .catch((err) => {
35
+ logger.error(`${ApiKeyRepoImpl.name} | ${this.getApiKey.name}() | Error (getApiKey): ${err}`);
36
+ throw err;
37
+ });
38
+ }
39
+
40
+ /**
41
+ * This method creates a new api key for the provided appId.
42
+ *
43
+ * @param appId
44
+ * @param createdBy
45
+ */
46
+ public async createApiKey(appId: string, createdBy: string): Promise<string> {
47
+ let apiKey: ApiKey;
48
+
49
+ // Check if api key exists for the provided appId. If exists, return it without
50
+ // creating new key.
51
+ try {
52
+ apiKey = await this.getApiKey(appId);
53
+ logger.debug(
54
+ `${ApiKeyRepoImpl.name} | ${this.createApiKey.name}() | API key already exists for the appId: ${appId}`,
55
+ );
56
+ logger.debug(`${ApiKeyRepoImpl.name} | ${this.createApiKey.name}() | API key: ${apiKey.key}`);
57
+ return apiKey.key;
58
+ } catch (err) {
59
+ if (err instanceof NotFoundError) {
60
+ logger.info(
61
+ `${ApiKeyRepoImpl.name} | ${this.createApiKey.name}() | API key doesn't exist for the appId: ${appId}. Will attempt to create new.`,
62
+ );
63
+ } else {
64
+ logger.error(err);
65
+ throw Error(`Unable to create API key. Please try again later.`);
66
+ }
67
+ }
68
+
69
+ logger.info(`${ApiKeyRepoImpl.name} | ${this.createApiKey.name}() | Creating new API key...`);
70
+ let apiToken = createRandomToken(); // create new random api token
71
+ await encrypt(apiToken, settings.aesEncryptionKey).then((value) => {
72
+ apiToken = value;
73
+ });
74
+ apiKey = apiKeyQueries.getApiKeyInstance(appId, apiToken, createdBy);
75
+ return cassandraDBHelpers
76
+ .execute(apiKeyQueries.insertApiKeyQuery, apiKeyQueries.apiKeyToDBParams(apiKey))
77
+ .then(() => {
78
+ logger.info(
79
+ `${ApiKeyRepoImpl.name} | ${this.createApiKey.name}() | API key created for appId ${appId}.`,
80
+ );
81
+ return decrypt(apiKey.key, settings.aesEncryptionKey);
82
+ })
83
+ .catch((error) => {
84
+ logger.error(
85
+ `${ApiKeyRepoImpl.name} | ${this.createApiKey.name}() | Error while creating api key ${error}`,
86
+ );
87
+ throw Error('Unable to create API key. Please try again later.');
88
+ });
89
+ }
90
+
91
+ /**
92
+ * This method updates api key for the provided appId.
93
+ *
94
+ * @param appId
95
+ * @param updatedBy
96
+ */
97
+ public async updateApiKey(appId: string, updatedBy: string): Promise<string> {
98
+ // Check if api key exists for the provided appId. If exists,
99
+ // update api key.
100
+ try {
101
+ await this.getApiKey(appId);
102
+ } catch (err) {
103
+ if (err instanceof NotFoundError) {
104
+ logger.info(
105
+ `${ApiKeyRepoImpl.name} | ${this.updateApiKey.name}() | API key does not exist for the appId: ${appId}`,
106
+ );
107
+ throw Error(`API key doesn't exist for the appId`);
108
+ } else {
109
+ logger.error(`${ApiKeyRepoImpl.name} | ${this.updateApiKey.name}() | Err: ${JSON.stringify(err)}`);
110
+ throw Error(`Unable to update API key. Please try again later.`);
111
+ }
112
+ }
113
+
114
+ logger.info(`${ApiKeyRepoImpl.name} | ${this.updateApiKey.name}() | Updating api key...`);
115
+ let apiToken = createRandomToken(); // create new random api token
116
+ await encrypt(apiToken, settings.aesEncryptionKey).then((value) => {
117
+ apiToken = value;
118
+ });
119
+ const apiKey = apiKeyQueries.getApiKeyInstance(appId, apiToken, updatedBy);
120
+ return cassandraDBHelpers
121
+ .execute(apiKeyQueries.updateApiKeyQuery, [apiToken, appId])
122
+ .then(() => {
123
+ logger.info(
124
+ `${ApiKeyRepoImpl.name} | ${this.updateApiKey.name}() | API key updated for appId: ${appId}.`,
125
+ );
126
+ return decrypt(apiKey.key, settings.aesEncryptionKey);
127
+ })
128
+ .catch((error) => {
129
+ logger.error(
130
+ `${ApiKeyRepoImpl.name} | ${this.updateApiKey.name}() | Error while updating api key ${error}`,
131
+ );
132
+ throw Error(`Unable to update Api key. Please try again later.`);
133
+ });
134
+ }
135
+ }
@@ -0,0 +1,10 @@
1
+ import { ApiKeyRepoImpl } from './ApiKeyRepo';
2
+
3
+ export class ApiKeyRepoFactory {
4
+ private static singleton: ApiKeyRepoImpl;
5
+
6
+ static accessOrCreateSingleton(): ApiKeyRepoImpl {
7
+ this.singleton = this.singleton || new ApiKeyRepoImpl();
8
+ return this.singleton;
9
+ }
10
+ }
@@ -0,0 +1,33 @@
1
+ import { Client, types } from 'dse-driver';
2
+ import { logger } from '../logger/logger';
3
+ import { settings } from '../config/config';
4
+
5
+ export class CassandraClient {
6
+ public client: Client;
7
+
8
+ constructor() {
9
+ const cassandraClientSetup =
10
+ process.env.NODE_ENV === 'dev'
11
+ ? {
12
+ contactPoints: [settings.cassandraLocalHost],
13
+ keyspace: settings.cassandraLocalKeyspace,
14
+ protocolOptions: { maxVersion: types.protocolVersion.v4 },
15
+ localDataCenter: 'datacenter1',
16
+ }
17
+ : {
18
+ cloud: {
19
+ secureConnectBundle: settings.cassandraCertsFilePath,
20
+ },
21
+ credentials: {
22
+ username: settings.cassandraUsername,
23
+ password: settings.cassandraPassword,
24
+ },
25
+ keyspace: settings.cassandraKeyspace,
26
+ };
27
+ try {
28
+ this.client = new Client(cassandraClientSetup);
29
+ } catch (err) {
30
+ logger.error('Error creating Cassandra Client', err);
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,11 @@
1
+ import { Client } from 'dse-driver';
2
+ import { CassandraClient } from './CassandraClient';
3
+
4
+ export class CassandraClientFactory {
5
+ private static client: Client;
6
+
7
+ static accessOrCreateSingleton(): Client {
8
+ this.client = this.client || new CassandraClient().client;
9
+ return this.client;
10
+ }
11
+ }
@@ -0,0 +1,64 @@
1
+ import { types } from 'dse-driver';
2
+ import { toLower, toUpper } from 'lodash';
3
+ import { settings } from '../config/config';
4
+ import { logger } from '../logger/logger';
5
+ import { ApiKey } from '../types/ApiKey';
6
+ import { decrypt } from '../helpers/commons';
7
+
8
+ const CLASS_NAME = 'ApiKeyRepoQueries';
9
+
10
+ export function apiKeysTableName(): string {
11
+ return 'apiKeys';
12
+ }
13
+ export const apiKeyFields = ['app_id', 'key', 'created_by', 'created_date', 'updated_date'];
14
+ export const selectApiKeyByAppId = `select JSON * from apiKeys where app_id= ?`;
15
+ export const apiKeyInsertFields = apiKeyFields.join(',');
16
+ export const apiKeyInsertParams = apiKeyFields.map(() => '?').join(',');
17
+
18
+ export const insertApiKeyQuery = `insert into ${apiKeysTableName()}
19
+ (${apiKeyInsertFields}) values
20
+ (${apiKeyInsertParams})`;
21
+ export const updateApiKeyQuery = `update ${apiKeysTableName()} set key = ?
22
+ where app_id = ?`;
23
+ export const deleteApiKeyQuery = `delete from ${apiKeysTableName()} where app_id = ?`;
24
+
25
+ export function apiKeyToDBParams(apiKey: ApiKey): Array<string | Date> {
26
+ return [
27
+ toLower(apiKey.appId),
28
+ apiKey.key,
29
+ toUpper(apiKey.createdBy),
30
+ apiKey.createdDate,
31
+ apiKey.updatedDate,
32
+ ];
33
+ }
34
+
35
+ export function appKeyPKeyValues(appId: string): string[] {
36
+ const pkValues = [toLower(appId)];
37
+ logger.debug(`${CLASS_NAME} | ${appKeyPKeyValues.name}() | appKeyPKeyValues: ${pkValues}`);
38
+ return pkValues;
39
+ }
40
+
41
+ export async function rowToApiKey(row: types.Row): Promise<ApiKey> {
42
+ const decryptedKey: string = await decrypt(row.key, settings.aesEncryptionKey);
43
+ const apiKey: ApiKey = {
44
+ appId: row.app_id,
45
+ key: decryptedKey,
46
+ createdBy: row.createdBy,
47
+ createdDate: row.createdDate,
48
+ updatedDate: row.updatedDate,
49
+ };
50
+ logger.debug('Returning api key: ', apiKey, 'Row: ', row);
51
+ return apiKey;
52
+ }
53
+
54
+ export function getApiKeyInstance(appId: string, key: string, createdBy: string): ApiKey {
55
+ const now = new Date();
56
+ const apiKey: ApiKey = {
57
+ appId,
58
+ key,
59
+ createdBy,
60
+ createdDate: now,
61
+ updatedDate: now,
62
+ };
63
+ return apiKey;
64
+ }
@@ -0,0 +1,119 @@
1
+ import * as dotenv from 'dotenv';
2
+ import { merge } from 'lodash';
3
+ import { types, QueryOptions, ArrayOrObject } from 'dse-driver';
4
+ import { BatchQuery, UserSettingsDBRow } from '../types/settingsRepoTypes';
5
+ import { QueryResults } from '../types/QueryResultsTypes';
6
+ import { CassandraClientFactory } from './CassandraClientFactory';
7
+
8
+ dotenv.config();
9
+ const client = CassandraClientFactory.accessOrCreateSingleton();
10
+
11
+ export async function single(
12
+ query: string,
13
+ whereValues: (string | Date)[],
14
+ options?: QueryOptions,
15
+ ): Promise<types.Row> {
16
+ return new Promise((resolve: (row: types.Row) => void, reject: (err: Error) => void): void => {
17
+ const queryOptions = merge(
18
+ {
19
+ prepare: true,
20
+ consistency: types.consistencies.localQuorum,
21
+ },
22
+ options,
23
+ );
24
+
25
+ client.execute(query, whereValues, queryOptions, (err: Error, result: types.ResultSet) => {
26
+ if (err) {
27
+ reject(err);
28
+ } else {
29
+ const row: types.Row | null = result.first();
30
+ if (row === undefined || row === null) {
31
+ resolve(row as types.Row);
32
+ } else if (row !== null) {
33
+ resolve(row);
34
+ }
35
+ }
36
+ });
37
+ });
38
+ }
39
+
40
+ export async function batch(queries: BatchQuery[], options?: QueryOptions): Promise<types.ResultSet> {
41
+ const queryOptions = merge(
42
+ {
43
+ prepare: true,
44
+ consistency: types.consistencies.localQuorum,
45
+ },
46
+ options,
47
+ );
48
+
49
+ return client.batch(queries, queryOptions);
50
+ }
51
+
52
+ export async function shutdown(): Promise<void> {
53
+ client.shutdown();
54
+ }
55
+
56
+ export async function execute(
57
+ query: string,
58
+ params?: ArrayOrObject,
59
+ options?: QueryOptions,
60
+ ): Promise<types.ResultSet> {
61
+ const queryOptions = merge(
62
+ {
63
+ prepare: true,
64
+ consistency: types.consistencies.localQuorum,
65
+ },
66
+ options,
67
+ );
68
+
69
+ return client.execute(query, params, queryOptions);
70
+ }
71
+
72
+ export async function paginate(
73
+ query: string,
74
+ params: string[],
75
+ options?: QueryOptions,
76
+ ): Promise<QueryResults> {
77
+ const queryOptions = merge(
78
+ {
79
+ prepare: true,
80
+ consistency: types.consistencies.localQuorum,
81
+ },
82
+ options,
83
+ );
84
+
85
+ if (options && !options.pageState) {
86
+ delete queryOptions.pageState;
87
+ }
88
+
89
+ const queryResults: QueryResults = {};
90
+ const resultsArray: UserSettingsDBRow[] = [];
91
+ // tslint:disable-next-line
92
+ return new Promise<QueryResults>((resolve, reject) => {
93
+ client.eachRow(
94
+ query,
95
+ params,
96
+ queryOptions,
97
+ (n, result) => {
98
+ resultsArray.push(result as unknown as UserSettingsDBRow);
99
+ },
100
+ (err, result) => {
101
+ if (err) {
102
+ reject(err);
103
+ } else {
104
+ queryResults.settings = resultsArray;
105
+ queryResults.pageState = result.pageState;
106
+ resolve(queryResults);
107
+ }
108
+ },
109
+ );
110
+ });
111
+ }
112
+
113
+ export const cassandraDBHelpers = {
114
+ batch,
115
+ execute,
116
+ single,
117
+ shutdown,
118
+ paginate,
119
+ };