@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.
- package/package.json +9 -3
- package/settings-service/.eslintrc.js +4 -0
- package/settings-service/.node-version +1 -0
- package/settings-service/.prettierrc +6 -0
- package/settings-service/.whitesource +15 -0
- package/settings-service/LICENSE +4 -0
- package/settings-service/README.md +50 -0
- package/settings-service/build.yml +56 -0
- package/settings-service/collectCodeCoverage.js +9 -0
- package/settings-service/db/cassandra/Dockerfile +3 -0
- package/settings-service/db/cassandra/createkeyspace.dev.cql +4 -0
- package/settings-service/db/cassandra/createkeyspace.dev.sh +3 -0
- package/settings-service/db/cassandra/schema_001.cql +15 -0
- package/settings-service/db/cassandra/schema_002.cql +8 -0
- package/settings-service/db/cassandra/schema_003.cql +10 -0
- package/settings-service/db/cassandra/schema_004.cql +1 -0
- package/settings-service/db/cassandra/schema_005.cql +39 -0
- package/settings-service/db/cassandra/schema_006.cql +255 -0
- package/settings-service/db/cassandra/schema_007.cql +40 -0
- package/settings-service/db/cassandra/schema_008.cql +2 -0
- package/settings-service/db/cassandra/schema_009.cql +143 -0
- package/settings-service/db/cassandra/schema_010.cql +143 -0
- package/settings-service/db/cassandra/schema_011.cql +2 -0
- package/settings-service/db/cassandra/schema_012.cql +8 -0
- package/settings-service/jest.config.fn.js +3 -0
- package/settings-service/jest.config.it.js +3 -0
- package/settings-service/jest.config.js +14 -0
- package/settings-service/jest.config.unit.js +19 -0
- package/settings-service/jest.setup.js +11 -0
- package/settings-service/package-lock.json +11772 -0
- package/settings-service/package.json +101 -0
- package/settings-service/scripts/run-fn-tests.sh +3 -0
- package/settings-service/sonar-project.properties +3 -0
- package/settings-service/src/__tests__/functional/controller/ApiKeyController.fn.ts +132 -0
- package/settings-service/src/__tests__/functional/middleware/AuthMiddlewareNextGenSSO.fn.ts +82 -0
- package/settings-service/src/__tests__/functional/repo/settingsRepo.fn.ts +302 -0
- package/settings-service/src/__tests__/functional/unified-profile/unified-profile.fn.ts +66 -0
- package/settings-service/src/__tests__/integration/repo/ApiKeyRepo.it.ts +43 -0
- package/settings-service/src/__tests__/integration/repo/settingsRepo.it.ts +142 -0
- package/settings-service/src/__tests__/integration/unified-profile/unified-profile.it.ts +31 -0
- package/settings-service/src/__tests__/unit/ErrResponse.ts +4 -0
- package/settings-service/src/__tests__/unit/JWTResponse.ts +18 -0
- package/settings-service/src/__tests__/unit/bluepagesResponse.ts +25 -0
- package/settings-service/src/__tests__/unit/controller/ApiKeyController.spec.ts +217 -0
- package/settings-service/src/__tests__/unit/controller/AppSettingsController.spec.ts +133 -0
- package/settings-service/src/__tests__/unit/controller/UserSettingsController.spec.ts +328 -0
- package/settings-service/src/__tests__/unit/controller/getAllSettings.spec.ts +83 -0
- package/settings-service/src/__tests__/unit/middleware/AuthMiddlewareNextGenSSO.spec.ts +282 -0
- package/settings-service/src/__tests__/unit/middleware/AuthenticationMiddleware.spec.ts +494 -0
- package/settings-service/src/__tests__/unit/repo/ApiKeyRepo.spec.ts +194 -0
- package/settings-service/src/__tests__/unit/repo/getAllSettings.spec.ts +100 -0
- package/settings-service/src/__tests__/unit/repo/getUserSettingsRepo.spec.ts +249 -0
- package/settings-service/src/__tests__/unit/repo/settingsRepo.spec.ts +614 -0
- package/settings-service/src/__tests__/unit/unified-profile/UnifiedProfileClient.spec.ts +31 -0
- package/settings-service/src/__tests__/unit/unified-profile/unifiedProfileUtils.spec.ts +36 -0
- package/settings-service/src/__tests__/utils/test-utils.ts +41 -0
- package/settings-service/src/config/config.ts +190 -0
- package/settings-service/src/controller/ApiKeyController.ts +114 -0
- package/settings-service/src/controller/AppSettingsController.ts +137 -0
- package/settings-service/src/controller/UserSettingsController.ts +202 -0
- package/settings-service/src/helpers/commons.ts +69 -0
- package/settings-service/src/logger/logger.ts +17 -0
- package/settings-service/src/middleware/AuthenticationMiddleware.ts +486 -0
- package/settings-service/src/middleware/AuthenticationMiddlewareFactory.ts +10 -0
- package/settings-service/src/repo/ApiKeyRepo.ts +135 -0
- package/settings-service/src/repo/ApiKeyRepoFactory.ts +10 -0
- package/settings-service/src/repo/CassandraClient.ts +33 -0
- package/settings-service/src/repo/CassandraClientFactory.ts +11 -0
- package/settings-service/src/repo/apiKeyQueries.ts +64 -0
- package/settings-service/src/repo/cassandraDBHelpers.ts +119 -0
- package/settings-service/src/repo/settingsRepo.ts +388 -0
- package/settings-service/src/repo/settingsRepoFactory.ts +10 -0
- package/settings-service/src/repo/settingsRepoQueries.ts +62 -0
- package/settings-service/src/routes/apiKeyRoutes.ts +27 -0
- package/settings-service/src/routes/appSettingsRoutes.ts +30 -0
- package/settings-service/src/routes/healthCheck.ts +10 -0
- package/settings-service/src/routes/swagger.ts +8 -0
- package/settings-service/src/routes/userSettingsRoutes.ts +30 -0
- package/settings-service/src/server.ts +77 -0
- package/settings-service/src/swagger.json +732 -0
- package/settings-service/src/types/ApiKey.ts +19 -0
- package/settings-service/src/types/IRequest.ts +9 -0
- package/settings-service/src/types/IRequestAuthorization.ts +5 -0
- package/settings-service/src/types/IRouteOptions.ts +5 -0
- package/settings-service/src/types/QueryResultsTypes.ts +6 -0
- package/settings-service/src/types/UserSettingsControllerTypes.ts +5 -0
- package/settings-service/src/types/W3IdUser.ts +36 -0
- package/settings-service/src/types/settingsRepoTypes.ts +61 -0
- package/settings-service/src/types/unifiedProfileTypes.ts +10 -0
- package/settings-service/src/unified-profile/UnifiedProfileClient.ts +29 -0
- package/settings-service/src/unified-profile/UnifiedProfileClientFactory.ts +10 -0
- package/settings-service/src/unified-profile/unifiedProfileUtils.ts +22 -0
- package/settings-service/src/util/downloadCassandra.ts +34 -0
- package/settings-service/src/util/isocodeMapper.ts +22 -0
- package/settings-service/src/util/languages.ts +1457 -0
- package/settings-service/test_resources/mockApiKeyDBResult.json +8 -0
- package/settings-service/tsconfig.json +40 -0
- package/README.md +0 -5
@@ -0,0 +1,388 @@
|
|
1
|
+
import { types } from 'dse-driver';
|
2
|
+
import { toUpper } from 'lodash';
|
3
|
+
import { QueryResults } from 'types/QueryResultsTypes';
|
4
|
+
import { logger } from '../logger/logger';
|
5
|
+
import {
|
6
|
+
AppSettingsConfigDBRow,
|
7
|
+
AppSettingsResponse,
|
8
|
+
BatchQuery,
|
9
|
+
DeprecatedValues,
|
10
|
+
FetchAndMapLanguagesArgs,
|
11
|
+
GetAllSettingsOptions,
|
12
|
+
UpdateAppSettingsArgs,
|
13
|
+
UserSettings,
|
14
|
+
UserSettingsDBRow,
|
15
|
+
} from '../types/settingsRepoTypes';
|
16
|
+
import { getUnifiedProfile } from '../unified-profile/unifiedProfileUtils';
|
17
|
+
import { reverseMapFullNameToIsoCode } from '../util/isocodeMapper';
|
18
|
+
import languages from '../util/languages';
|
19
|
+
import { cassandraDBHelpers } from './cassandraDBHelpers';
|
20
|
+
import * as srq from './settingsRepoQueries';
|
21
|
+
|
22
|
+
export interface SettingsRepo {
|
23
|
+
getUserSettings(userId: string, appId: string): Promise<UserSettings>;
|
24
|
+
|
25
|
+
updateUserSettings(
|
26
|
+
userId: string,
|
27
|
+
appId: string,
|
28
|
+
settingName: string,
|
29
|
+
settingValue: string,
|
30
|
+
): Promise<boolean>;
|
31
|
+
|
32
|
+
deleteUserSettings(userId: string): Promise<boolean>;
|
33
|
+
|
34
|
+
getAppSettings(appId: string, settingName: string | undefined): Promise<AppSettingsResponse>;
|
35
|
+
|
36
|
+
updateAppSettings(updateAppSettingsArgs: UpdateAppSettingsArgs): Promise<boolean>;
|
37
|
+
|
38
|
+
deleteAppSettings(appId: string, settingName: string): Promise<boolean>;
|
39
|
+
|
40
|
+
checkValueIsValidOption(updateValue: string[], optionsArray: string[]): boolean;
|
41
|
+
|
42
|
+
fetchAndMapLanguageValues(fetchAndMapLanguagesArgs: FetchAndMapLanguagesArgs): Promise<UserSettings>;
|
43
|
+
|
44
|
+
transformAndUpdateDeprecatedValues(deprecatedValues: DeprecatedValues, dbRow: UserSettingsDBRow): string;
|
45
|
+
|
46
|
+
getAllSettings(options: GetAllSettingsOptions): Promise<QueryResults>;
|
47
|
+
}
|
48
|
+
|
49
|
+
export class SettingsRepoCassandra implements SettingsRepo {
|
50
|
+
public async getUserSettings(userId: string, appId: string): Promise<UserSettings> {
|
51
|
+
const filter: AppSettingsResponse = await this.getAppSettings(appId, undefined);
|
52
|
+
|
53
|
+
return cassandraDBHelpers
|
54
|
+
.execute(srq.fetchUserSettingsDataQuery, [toUpper(userId), appId], { prepare: true })
|
55
|
+
.then(async (results: types.ResultSet) => {
|
56
|
+
const response: types.Row[] = results.rows;
|
57
|
+
logger.debug(
|
58
|
+
`${SettingsRepoCassandra.name} | ${this.getUserSettings.name}() | List size of userSettings :: ${response.length}`,
|
59
|
+
);
|
60
|
+
|
61
|
+
const result: UserSettings = {};
|
62
|
+
|
63
|
+
for (const row of response) {
|
64
|
+
const retrievedSettingName = row.setting_name;
|
65
|
+
if (retrievedSettingName in filter) {
|
66
|
+
const deprecatedValues = filter[retrievedSettingName].deprecated_values;
|
67
|
+
const retrievedSettingValue = deprecatedValues
|
68
|
+
? this.transformAndUpdateDeprecatedValues(deprecatedValues, row as unknown as UserSettingsDBRow)
|
69
|
+
: row.setting_value;
|
70
|
+
if (
|
71
|
+
retrievedSettingName != null &&
|
72
|
+
this.checkValueIsValidOption(
|
73
|
+
retrievedSettingValue?.split(','),
|
74
|
+
filter[retrievedSettingName].options,
|
75
|
+
)
|
76
|
+
) {
|
77
|
+
result[retrievedSettingName] =
|
78
|
+
filter[retrievedSettingName].setting_type === 'array'
|
79
|
+
? retrievedSettingValue?.split(',')
|
80
|
+
: retrievedSettingValue;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
if (appId === 'general') {
|
86
|
+
const updatedLanguageValues = await this.fetchAndMapLanguageValues({
|
87
|
+
userId,
|
88
|
+
appId,
|
89
|
+
result,
|
90
|
+
filter,
|
91
|
+
settingsDBRows: response as unknown as UserSettingsDBRow[],
|
92
|
+
});
|
93
|
+
result.secondaryLanguages = result.secondaryLanguages
|
94
|
+
? result.secondaryLanguages
|
95
|
+
: updatedLanguageValues.secondaryLanguages;
|
96
|
+
result.primaryLanguage = result.primaryLanguage
|
97
|
+
? result.primaryLanguage
|
98
|
+
: updatedLanguageValues.primaryLanguage;
|
99
|
+
}
|
100
|
+
for (const setting in filter) {
|
101
|
+
if (!result[setting]) {
|
102
|
+
result[setting] = filter[setting].default || null;
|
103
|
+
if (filter[setting].setting_type === 'array' && !result[setting]) {
|
104
|
+
result[setting] = [];
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
return result;
|
109
|
+
})
|
110
|
+
.catch((error) => {
|
111
|
+
logger.error(
|
112
|
+
`${SettingsRepoCassandra.name} | ${this.getUserSettings.name}() | Error while reading userSettings ${error}`,
|
113
|
+
);
|
114
|
+
throw Error(`Error while reading getUserSettings`);
|
115
|
+
});
|
116
|
+
}
|
117
|
+
|
118
|
+
public async updateUserSettings(
|
119
|
+
userId: string,
|
120
|
+
appId: string,
|
121
|
+
settingName: string,
|
122
|
+
settingValue: string,
|
123
|
+
): Promise<boolean> {
|
124
|
+
const batchQueries: BatchQuery[] = [];
|
125
|
+
batchQueries.push(
|
126
|
+
{
|
127
|
+
query: srq.updateUserSettingsDataQuery,
|
128
|
+
params: [settingValue, userId, appId, settingName],
|
129
|
+
},
|
130
|
+
{
|
131
|
+
query: srq.updateUserSettingsByAppQuery,
|
132
|
+
params: [settingValue, appId, settingName, userId],
|
133
|
+
},
|
134
|
+
);
|
135
|
+
await cassandraDBHelpers.batch(batchQueries);
|
136
|
+
return true;
|
137
|
+
}
|
138
|
+
|
139
|
+
public async deleteUserSettings(userId: string): Promise<boolean> {
|
140
|
+
const settings = await cassandraDBHelpers.execute(srq.fetchUserSettingsById, [userId], { prepare: true });
|
141
|
+
const batchQueries: BatchQuery[] = [];
|
142
|
+
batchQueries.push({
|
143
|
+
query: srq.deleteUserSettingsDataQuery,
|
144
|
+
params: [userId],
|
145
|
+
});
|
146
|
+
settings.rows.forEach((row: types.Row) => {
|
147
|
+
batchQueries.push({
|
148
|
+
query: srq.deleteUserSettingsByAppQuery,
|
149
|
+
params: [row.app_id, row.setting_name, userId],
|
150
|
+
});
|
151
|
+
});
|
152
|
+
await cassandraDBHelpers.batch(batchQueries);
|
153
|
+
|
154
|
+
return true;
|
155
|
+
}
|
156
|
+
|
157
|
+
public async getAppSettings(appId: string, settingName: string | undefined): Promise<AppSettingsResponse> {
|
158
|
+
let query = srq.fetchAppSettingsDataQuery;
|
159
|
+
let params = [appId];
|
160
|
+
|
161
|
+
if (settingName) {
|
162
|
+
query = srq.fetchSingleAppSettingsDataQuery;
|
163
|
+
params = [appId, settingName];
|
164
|
+
}
|
165
|
+
return cassandraDBHelpers
|
166
|
+
.execute(query, params, { prepare: true })
|
167
|
+
.then((results: types.ResultSet) => {
|
168
|
+
const response: AppSettingsConfigDBRow[] = results.rows as unknown as AppSettingsConfigDBRow[];
|
169
|
+
logger.debug(
|
170
|
+
`${SettingsRepoCassandra.name} | ${this.getAppSettings.name}() | List size of appSettings :: ${response.length}`,
|
171
|
+
);
|
172
|
+
const result = {};
|
173
|
+
for (const row of response) {
|
174
|
+
if (row.setting_name) {
|
175
|
+
result[row.setting_name] = {
|
176
|
+
default: row.setting_default,
|
177
|
+
options: row.setting_options,
|
178
|
+
};
|
179
|
+
if (row.setting_type) {
|
180
|
+
result[row.setting_name].setting_type = row.setting_type;
|
181
|
+
}
|
182
|
+
if (row.deprecated_values) {
|
183
|
+
result[row.setting_name].deprecated_values = JSON.parse(row.deprecated_values);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
}
|
187
|
+
return result;
|
188
|
+
})
|
189
|
+
.catch((error) => {
|
190
|
+
logger.error(
|
191
|
+
`${SettingsRepoCassandra.name} | ${this.getAppSettings.name}() | Error while reading appSettings ${error}`,
|
192
|
+
);
|
193
|
+
throw Error(`Error while reading getAppSettings`);
|
194
|
+
});
|
195
|
+
}
|
196
|
+
|
197
|
+
public async updateAppSettings({
|
198
|
+
appId,
|
199
|
+
settingName,
|
200
|
+
settingDefault,
|
201
|
+
settingOptions,
|
202
|
+
settingType,
|
203
|
+
deprecatedValues,
|
204
|
+
}: UpdateAppSettingsArgs): Promise<boolean> {
|
205
|
+
return cassandraDBHelpers
|
206
|
+
.execute(
|
207
|
+
srq.updateAppSettingsDataQuery,
|
208
|
+
[
|
209
|
+
settingDefault ?? null,
|
210
|
+
settingOptions,
|
211
|
+
settingType ?? null,
|
212
|
+
deprecatedValues ?? null,
|
213
|
+
appId,
|
214
|
+
settingName,
|
215
|
+
],
|
216
|
+
{ prepare: true },
|
217
|
+
)
|
218
|
+
.then(() => {
|
219
|
+
logger.debug(
|
220
|
+
`${SettingsRepoCassandra.name} | ${this.updateAppSettings.name}() | Success updating AppSettings`,
|
221
|
+
);
|
222
|
+
return true;
|
223
|
+
})
|
224
|
+
.catch((error) => {
|
225
|
+
logger.error(
|
226
|
+
`${SettingsRepoCassandra.name} | ${this.updateAppSettings.name}() | Error while updating appSettings ${error}`,
|
227
|
+
);
|
228
|
+
throw Error(`Error while updating AppSettings`);
|
229
|
+
});
|
230
|
+
}
|
231
|
+
|
232
|
+
public async deleteAppSettings(appId: string, settingName: string): Promise<boolean> {
|
233
|
+
return cassandraDBHelpers
|
234
|
+
.execute(srq.deleteAppSettingsDataQuery, [appId, settingName], { prepare: true })
|
235
|
+
.then(() => {
|
236
|
+
logger.debug(
|
237
|
+
`${SettingsRepoCassandra.name} | ${this.deleteAppSettings.name}() | Success deleted app settings`,
|
238
|
+
);
|
239
|
+
return true;
|
240
|
+
})
|
241
|
+
.catch((error) => {
|
242
|
+
logger.error(
|
243
|
+
`${SettingsRepoCassandra.name} | ${this.deleteAppSettings.name}() | Error while deleting appSettings ${error}`,
|
244
|
+
);
|
245
|
+
throw Error(`Error while deleting AppSettings`);
|
246
|
+
});
|
247
|
+
}
|
248
|
+
|
249
|
+
public checkValueIsValidOption(updatedValue: string[], optionsArray: string[]): boolean {
|
250
|
+
if (Array.isArray(updatedValue)) {
|
251
|
+
for (const eachValue of updatedValue) {
|
252
|
+
if (!optionsArray.includes(eachValue)) {
|
253
|
+
return false;
|
254
|
+
}
|
255
|
+
}
|
256
|
+
} else if (!optionsArray.includes(updatedValue)) {
|
257
|
+
return false;
|
258
|
+
}
|
259
|
+
return true;
|
260
|
+
}
|
261
|
+
|
262
|
+
public async fetchAndMapLanguageValues({
|
263
|
+
userId,
|
264
|
+
appId,
|
265
|
+
result,
|
266
|
+
filter,
|
267
|
+
settingsDBRows,
|
268
|
+
}: FetchAndMapLanguagesArgs): Promise<UserSettings> {
|
269
|
+
const updatedLanguageSettings: UserSettings = {};
|
270
|
+
// check if they have ever had a secondary languages value set
|
271
|
+
const hasSecondaryLanguagesRow = settingsDBRows.some(
|
272
|
+
(row: UserSettingsDBRow) => row.setting_name === 'secondaryLanguages',
|
273
|
+
);
|
274
|
+
|
275
|
+
if (!result.primaryLanguage || (!result.secondaryLanguages && !hasSecondaryLanguagesRow)) {
|
276
|
+
const profile = await getUnifiedProfile(userId);
|
277
|
+
|
278
|
+
if (profile && profile.content) {
|
279
|
+
if (!result.primaryLanguage) {
|
280
|
+
if (profile.content.languages && profile.content.languages.length === 1) {
|
281
|
+
updatedLanguageSettings.primaryLanguage = reverseMapFullNameToIsoCode(
|
282
|
+
profile.content.languages[0],
|
283
|
+
languages,
|
284
|
+
);
|
285
|
+
}
|
286
|
+
if (profile.content.preferredLanguage && !result.primaryLanguage) {
|
287
|
+
updatedLanguageSettings.primaryLanguage = reverseMapFullNameToIsoCode(
|
288
|
+
profile.content.preferredLanguage,
|
289
|
+
languages,
|
290
|
+
);
|
291
|
+
}
|
292
|
+
// If valid primaryLanguage then, Store UP language as the primaryLanguage in user settings.
|
293
|
+
// Else store the default language as pre-configured in app_config
|
294
|
+
if (updatedLanguageSettings.primaryLanguage) {
|
295
|
+
await this.updateUserSettings(
|
296
|
+
userId,
|
297
|
+
appId,
|
298
|
+
'primaryLanguage',
|
299
|
+
updatedLanguageSettings.primaryLanguage as string,
|
300
|
+
);
|
301
|
+
logger.info(
|
302
|
+
`${SettingsRepoCassandra.name} | ${this.getUserSettings.name}() | Persisted UP primaryLanguage to user settings`,
|
303
|
+
);
|
304
|
+
} else {
|
305
|
+
if (filter.primaryLanguage.default) {
|
306
|
+
await this.updateUserSettings(userId, appId, 'primaryLanguage', filter.primaryLanguage.default);
|
307
|
+
}
|
308
|
+
logger.info(
|
309
|
+
`${SettingsRepoCassandra.name} | ${this.fetchAndMapLanguageValues.name}() | Persisted default primaryLanguage to user settings`,
|
310
|
+
);
|
311
|
+
}
|
312
|
+
}
|
313
|
+
|
314
|
+
if (!result.secondaryLanguages) {
|
315
|
+
if (profile.content.languages && profile.content.languages.length > 1) {
|
316
|
+
let secondaryLanguagesArray = profile.content.languages.map((language: string) => {
|
317
|
+
return reverseMapFullNameToIsoCode(language, languages);
|
318
|
+
});
|
319
|
+
secondaryLanguagesArray = result.primaryLanguage
|
320
|
+
? secondaryLanguagesArray.filter((language: string) => language !== result.primaryLanguage)
|
321
|
+
: secondaryLanguagesArray.filter(
|
322
|
+
(language: string) => language !== filter.primaryLanguage.default,
|
323
|
+
);
|
324
|
+
updatedLanguageSettings.secondaryLanguages = secondaryLanguagesArray;
|
325
|
+
}
|
326
|
+
// If valid secondaryLanguages then, Store UP secondaryLanguages as the secondaryLanguages value in user settings.
|
327
|
+
// Else store an empty string so we don't make the same call again
|
328
|
+
if (updatedLanguageSettings.secondaryLanguages) {
|
329
|
+
await this.updateUserSettings(
|
330
|
+
userId,
|
331
|
+
appId,
|
332
|
+
'secondaryLanguages',
|
333
|
+
(updatedLanguageSettings.secondaryLanguages as string[]).join(','),
|
334
|
+
);
|
335
|
+
logger.info(
|
336
|
+
`${SettingsRepoCassandra.name} | ${this.fetchAndMapLanguageValues.name}() | Persisted UP secondaryLanguages to user settings`,
|
337
|
+
);
|
338
|
+
} else {
|
339
|
+
await this.updateUserSettings(userId, appId, 'secondaryLanguages', '');
|
340
|
+
logger.info(
|
341
|
+
`${SettingsRepoCassandra.name} | ${this.fetchAndMapLanguageValues.name}() | Persisted placeholder for secondaryLanguages to user settings`,
|
342
|
+
);
|
343
|
+
updatedLanguageSettings.secondaryLanguages = [];
|
344
|
+
}
|
345
|
+
}
|
346
|
+
/* eslint-enable no-param-reassign */
|
347
|
+
}
|
348
|
+
}
|
349
|
+
return updatedLanguageSettings;
|
350
|
+
}
|
351
|
+
|
352
|
+
public transformAndUpdateDeprecatedValues(
|
353
|
+
deprecatedValues: DeprecatedValues,
|
354
|
+
dbRow: UserSettingsDBRow,
|
355
|
+
): string {
|
356
|
+
let updateFlag = false;
|
357
|
+
const updatedValue = dbRow.setting_value?.split(',')
|
358
|
+
.map((value: string) => {
|
359
|
+
if (deprecatedValues[value]) {
|
360
|
+
updateFlag = true;
|
361
|
+
return deprecatedValues[value];
|
362
|
+
}
|
363
|
+
return value;
|
364
|
+
})
|
365
|
+
.join(',');
|
366
|
+
|
367
|
+
if (updateFlag) {
|
368
|
+
logger.debug(
|
369
|
+
`${SettingsRepoCassandra.name} | ${this.transformAndUpdateDeprecatedValues.name}() | Updating deprecated user setting values`,
|
370
|
+
);
|
371
|
+
this.updateUserSettings(dbRow.user_id, dbRow.app_id, dbRow.setting_name, updatedValue);
|
372
|
+
}
|
373
|
+
return updatedValue;
|
374
|
+
}
|
375
|
+
|
376
|
+
public async getAllSettings(options: GetAllSettingsOptions): Promise<QueryResults> {
|
377
|
+
const { pageState = '', settingName, fetchSize = 500, appId }: GetAllSettingsOptions = options;
|
378
|
+
if (appId) {
|
379
|
+
return settingName
|
380
|
+
? cassandraDBHelpers.paginate(srq.allUserSettingsBySettingNameQuery, [appId, settingName], {
|
381
|
+
pageState,
|
382
|
+
fetchSize,
|
383
|
+
})
|
384
|
+
: cassandraDBHelpers.paginate(srq.allUserSettingsByAppIdQuery, [appId], { pageState, fetchSize });
|
385
|
+
}
|
386
|
+
return cassandraDBHelpers.paginate(srq.allUserSettingsQuery, [], { pageState, fetchSize });
|
387
|
+
}
|
388
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { SettingsRepoCassandra } from './settingsRepo';
|
2
|
+
|
3
|
+
export class SettingsRepoFactory {
|
4
|
+
private static singleton: SettingsRepoCassandra;
|
5
|
+
|
6
|
+
static accessOrCreateSingleton(): SettingsRepoCassandra {
|
7
|
+
this.singleton = this.singleton || new SettingsRepoCassandra();
|
8
|
+
return this.singleton;
|
9
|
+
}
|
10
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
export const fetchUserSettingsDataQuery = `
|
2
|
+
SELECT *
|
3
|
+
FROM user_settings
|
4
|
+
WHERE user_id = ? AND app_id = ?
|
5
|
+
`;
|
6
|
+
export const updateUserSettingsDataQuery = `
|
7
|
+
UPDATE user_settings
|
8
|
+
SET setting_value = ?
|
9
|
+
WHERE user_id = ? AND app_id = ? AND setting_name = ?
|
10
|
+
`;
|
11
|
+
export const deleteUserSettingsDataQuery = `
|
12
|
+
DELETE FROM user_settings
|
13
|
+
WHERE user_id = ?
|
14
|
+
`;
|
15
|
+
export const fetchAppSettingsDataQuery = `
|
16
|
+
SELECT *
|
17
|
+
FROM app_settings_config
|
18
|
+
WHERE app_id = ?
|
19
|
+
ORDER BY setting_name ASC
|
20
|
+
`;
|
21
|
+
export const fetchSingleAppSettingsDataQuery = `
|
22
|
+
SELECT *
|
23
|
+
FROM app_settings_config
|
24
|
+
WHERE app_id = ? and setting_name = ?
|
25
|
+
`;
|
26
|
+
export const updateAppSettingsDataQuery = `
|
27
|
+
UPDATE app_settings_config
|
28
|
+
SET setting_default = ?, setting_options = ?, setting_type = ? , deprecated_values = ?
|
29
|
+
WHERE app_id = ? AND setting_name = ?
|
30
|
+
`;
|
31
|
+
export const deleteAppSettingsDataQuery = `
|
32
|
+
DELETE FROM app_settings_config
|
33
|
+
WHERE app_id = ? AND setting_name = ?
|
34
|
+
`;
|
35
|
+
export const updateUserSettingsByAppQuery = `
|
36
|
+
UPDATE user_settings_by_app
|
37
|
+
SET setting_value = ?
|
38
|
+
WHERE app_id = ? AND setting_name = ? AND user_id = ?
|
39
|
+
`;
|
40
|
+
export const deleteUserSettingsByAppQuery = `
|
41
|
+
DELETE FROM user_settings_by_app
|
42
|
+
WHERE app_id = ? AND setting_name = ? AND user_id = ?
|
43
|
+
`;
|
44
|
+
export const fetchUserSettingsById = `
|
45
|
+
SELECT *
|
46
|
+
FROM user_settings
|
47
|
+
WHERE user_id = ?
|
48
|
+
`;
|
49
|
+
export const allUserSettingsQuery = `
|
50
|
+
SELECT *
|
51
|
+
FROM user_settings
|
52
|
+
`;
|
53
|
+
export const allUserSettingsBySettingNameQuery = `
|
54
|
+
SELECT *
|
55
|
+
FROM user_settings_by_app
|
56
|
+
WHERE app_id = ? AND setting_name = ?
|
57
|
+
`;
|
58
|
+
export const allUserSettingsByAppIdQuery = `
|
59
|
+
SELECT *
|
60
|
+
FROM user_settings_by_app
|
61
|
+
WHERE app_id = ?
|
62
|
+
`;
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import restify from 'restify';
|
2
|
+
import { fetchApiKey, postApiKey, putApiKey } from '../controller/ApiKeyController';
|
3
|
+
import { AuthenticationMiddleware } from '../middleware/AuthenticationMiddleware';
|
4
|
+
|
5
|
+
export default function apiKeyRoutes(server: restify.Server): void {
|
6
|
+
server.get(
|
7
|
+
AuthenticationMiddleware.apiKeyPath,
|
8
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
9
|
+
AuthenticationMiddleware.checkAuthentication,
|
10
|
+
AuthenticationMiddleware.checkPostAuthentication,
|
11
|
+
fetchApiKey,
|
12
|
+
);
|
13
|
+
server.post(
|
14
|
+
AuthenticationMiddleware.apiKeyPath,
|
15
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
16
|
+
AuthenticationMiddleware.checkAuthentication,
|
17
|
+
AuthenticationMiddleware.checkPostAuthentication,
|
18
|
+
postApiKey,
|
19
|
+
);
|
20
|
+
server.put(
|
21
|
+
AuthenticationMiddleware.apiKeyPath,
|
22
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
23
|
+
AuthenticationMiddleware.checkAuthentication,
|
24
|
+
AuthenticationMiddleware.checkPostAuthentication,
|
25
|
+
putApiKey,
|
26
|
+
);
|
27
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import restify from 'restify';
|
2
|
+
import { deleteAppSettings, getAppSettings, postAppSettings } from '../controller/AppSettingsController';
|
3
|
+
import { AuthenticationMiddleware } from '../middleware/AuthenticationMiddleware';
|
4
|
+
|
5
|
+
export default function appSettingsRoutes(server: restify.Server): void {
|
6
|
+
server.get(
|
7
|
+
AuthenticationMiddleware.allAppSettingsPath,
|
8
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
9
|
+
AuthenticationMiddleware.checkAuthentication,
|
10
|
+
getAppSettings,
|
11
|
+
);
|
12
|
+
server.get(
|
13
|
+
AuthenticationMiddleware.singleAppSettingPath,
|
14
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
15
|
+
AuthenticationMiddleware.checkAuthentication,
|
16
|
+
getAppSettings,
|
17
|
+
);
|
18
|
+
server.post(
|
19
|
+
AuthenticationMiddleware.singleAppSettingPath,
|
20
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
21
|
+
AuthenticationMiddleware.checkAuthentication,
|
22
|
+
postAppSettings,
|
23
|
+
);
|
24
|
+
server.del(
|
25
|
+
AuthenticationMiddleware.singleAppSettingPath,
|
26
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
27
|
+
AuthenticationMiddleware.checkAuthentication,
|
28
|
+
deleteAppSettings,
|
29
|
+
);
|
30
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import restify from 'restify';
|
2
|
+
import { logger } from '../logger/logger';
|
3
|
+
|
4
|
+
export default function healthCheck(server: restify.Server): void {
|
5
|
+
server.get('/health/ping', (req, res, next) => {
|
6
|
+
logger.debug('Health check service pinged...');
|
7
|
+
res.send('OK');
|
8
|
+
next();
|
9
|
+
});
|
10
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import restify from 'restify';
|
2
|
+
import swaggerUiRestify from 'swagger-ui-restify';
|
3
|
+
import swaggerJson from '../swagger.json';
|
4
|
+
|
5
|
+
export default function swagger(server: restify.Server): void {
|
6
|
+
server.get('/:', swaggerUiRestify.serveFiles(swaggerJson));
|
7
|
+
server.get('/', swaggerUiRestify.setup(swaggerJson));
|
8
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import restify from 'restify';
|
2
|
+
import {
|
3
|
+
deleteUserSettings,
|
4
|
+
getAllSettings,
|
5
|
+
getUserSettings,
|
6
|
+
postUserSettings,
|
7
|
+
} from '../controller/UserSettingsController';
|
8
|
+
import { AuthenticationMiddleware } from '../middleware/AuthenticationMiddleware';
|
9
|
+
|
10
|
+
export default function userSettingsRoutes(server: restify.Server): void {
|
11
|
+
server.get(AuthenticationMiddleware.settingsPath, getUserSettings);
|
12
|
+
server.post(
|
13
|
+
AuthenticationMiddleware.settingsPath,
|
14
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
15
|
+
AuthenticationMiddleware.checkAuthentication,
|
16
|
+
postUserSettings,
|
17
|
+
);
|
18
|
+
server.get(
|
19
|
+
AuthenticationMiddleware.allSettingsPath,
|
20
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
21
|
+
AuthenticationMiddleware.checkAuthentication,
|
22
|
+
getAllSettings,
|
23
|
+
);
|
24
|
+
server.del(
|
25
|
+
AuthenticationMiddleware.deleteSettingsPath,
|
26
|
+
AuthenticationMiddleware.checkPreAuthentication,
|
27
|
+
AuthenticationMiddleware.checkAuthentication,
|
28
|
+
deleteUserSettings,
|
29
|
+
);
|
30
|
+
}
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import dotenv from 'dotenv';
|
2
|
+
import restify from 'restify';
|
3
|
+
import corsMiddleware from 'restify-cors-middleware';
|
4
|
+
import { settings } from './config/config';
|
5
|
+
import { logger } from './logger/logger';
|
6
|
+
import apiKeyRoutes from './routes/apiKeyRoutes';
|
7
|
+
import appSettingsRoutes from './routes/appSettingsRoutes';
|
8
|
+
import healthCheck from './routes/healthCheck';
|
9
|
+
import swagger from './routes/swagger';
|
10
|
+
import userSettingsRoutes from './routes/userSettingsRoutes';
|
11
|
+
import { downloadCassandra } from './util/downloadCassandra';
|
12
|
+
|
13
|
+
dotenv.config();
|
14
|
+
|
15
|
+
const cors = corsMiddleware({
|
16
|
+
preflightMaxAge: 5,
|
17
|
+
credentials: true,
|
18
|
+
origins: [
|
19
|
+
/^https?:\/\/localhost(:[\d]+)?$/,
|
20
|
+
/^https?:\/\/.+\.ibm\.com$/,
|
21
|
+
/^https?:\/\/.+\.ibm\.com(:[\d]+)$/,
|
22
|
+
],
|
23
|
+
allowHeaders: [
|
24
|
+
'X-Requested-With',
|
25
|
+
'Accept-Language',
|
26
|
+
'Content-Language',
|
27
|
+
'Last-Event-ID',
|
28
|
+
'X-HTTP-Method-Override',
|
29
|
+
'access-control-allow-origin',
|
30
|
+
'withcredentials',
|
31
|
+
'Origin',
|
32
|
+
'Authorization',
|
33
|
+
'Content-Type',
|
34
|
+
'Accept',
|
35
|
+
'Accept-Encoding',
|
36
|
+
'Access-Control-Allow-Credentials',
|
37
|
+
'Access-Control-Request-Method',
|
38
|
+
'Access-Control-Request-Headers',
|
39
|
+
'X-Up-Token',
|
40
|
+
'nextgen_sso',
|
41
|
+
],
|
42
|
+
exposeHeaders: ['API-Token-Expiry', 'Access-Control-Allow-Credentials'],
|
43
|
+
});
|
44
|
+
function initRoutes(server: restify.Server): void {
|
45
|
+
healthCheck(server);
|
46
|
+
swagger(server);
|
47
|
+
userSettingsRoutes(server);
|
48
|
+
appSettingsRoutes(server);
|
49
|
+
apiKeyRoutes(server);
|
50
|
+
}
|
51
|
+
|
52
|
+
function initServer(server: restify.Server): restify.Server {
|
53
|
+
server.use(restify.plugins.queryParser());
|
54
|
+
server.use(restify.plugins.bodyParser());
|
55
|
+
server.pre(cors.preflight);
|
56
|
+
server.use(cors.actual);
|
57
|
+
return server;
|
58
|
+
}
|
59
|
+
|
60
|
+
function getServer(): restify.Server {
|
61
|
+
const myServer = restify.createServer();
|
62
|
+
return myServer;
|
63
|
+
}
|
64
|
+
|
65
|
+
async function run(): Promise<void> {
|
66
|
+
const server = getServer();
|
67
|
+
await downloadCassandra();
|
68
|
+
initServer(server);
|
69
|
+
initRoutes(server);
|
70
|
+
|
71
|
+
server.listen(settings.apiPort, async () => {
|
72
|
+
logger.info(`Server is up and is listening on port: ${settings.apiPort}`);
|
73
|
+
logger.info(`Server: http://localhost:${settings.apiPort}`);
|
74
|
+
});
|
75
|
+
}
|
76
|
+
|
77
|
+
run();
|