@mimik/api-helper 3.0.1 → 3.0.3
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.
- package/README.md +23 -20
- package/index.js +37 -32
- package/lib/baseHandlers.js +6 -24
- package/lib/common.js +1 -1
- package/lib/extract-helper.js +7 -12
- package/lib/oauthValidation-helper.js +2 -2
- package/lib/securityHandlers.js +59 -132
- package/package.json +18 -16
package/README.md
CHANGED
|
@@ -39,19 +39,19 @@ import { apiSetup, securityLib, getAPIFile, validateSecuritySchemes, extractProp
|
|
|
39
39
|
<a name="module_api-helper..apiSetup"></a>
|
|
40
40
|
|
|
41
41
|
### api-helper~apiSetup(setup, registeredOperations, securityHandlers, extraFormats, config, correlationId) ⇒ <code>Promise.<object></code>
|
|
42
|
-
|
|
42
|
+
Set up the API to be used for a service
|
|
43
43
|
|
|
44
44
|
**Kind**: inner method of [<code>api-helper</code>](#module_api-helper)
|
|
45
|
-
**Returns**: <code>Promise.<object></code> - The
|
|
45
|
+
**Returns**: <code>Promise.<object></code> - The initialized OpenAPIBackend instance.
|
|
46
46
|
**Category**: async
|
|
47
47
|
**Throws**:
|
|
48
48
|
|
|
49
|
-
- <code>
|
|
49
|
+
- <code>Error</code> Rejects with an error if the initialization failed.
|
|
50
50
|
|
|
51
51
|
The following scheme names are reserved: `SystemSecurity`, `AdminSecurity`, `UserSecurity`, `PeerSecurity`, `ApiKeySecurity`.
|
|
52
52
|
The following security schemes can be defaulted: `SystemSecurity`, `AdminSecurity`, `UserSecurity`, `ApiKeySecurity`.
|
|
53
53
|
The secOptions in the options property passed when using `init` allows the following operations:
|
|
54
|
-
- introduce a
|
|
54
|
+
- introduce a custom security scheme, in this case secOptions contains: { newSecurityScheme: {function}newSecurityHandler },
|
|
55
55
|
- disable a security scheme that is defined in the swagger API, in this case secOptions contains: { securitySchemeToDisable: { {boolean}notEnabled: true } },
|
|
56
56
|
- overwrite an existing security scheme, in this case secOptions contains: { securitySchemeToOverwrite: {function}newSecurityHandler }.
|
|
57
57
|
If the secOptions is not present either to introduce, disable or overwrite a security scheme that is present in the swagger API file an error is generated.
|
|
@@ -64,23 +64,26 @@ The default formats for validation are: `date`, `time`, `date-time`, `byte`, `uu
|
|
|
64
64
|
| Param | Type | Description |
|
|
65
65
|
| --- | --- | --- |
|
|
66
66
|
| setup | <code>object</code> | Object containing the apiFilename and the existing security schemes in the API definition. |
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
67
|
+
| setup.apiFilename | [<code>PATH</code>](#PATH) | Path to the resolved API definition file. |
|
|
68
|
+
| setup.existingSecuritySchemes | <code>Array.<string></code> | Known security scheme names present in the API definition. |
|
|
69
|
+
| setup.definedSecuritySchemes | <code>Array.<string></code> | All security scheme names defined in the API definition. |
|
|
70
|
+
| registeredOperations | <code>object</code> | Map of operationId to handler function to register for the API. |
|
|
71
|
+
| securityHandlers | <code>object</code> | Map of security scheme name to handler object to add for the service. |
|
|
72
|
+
| extraFormats | <code>object</code> | Map of format name to format definition for validating properties. Each entry is either an empty object (to use a built-in ajv-formats format) or an object with `type` and `validate` properties (to define a custom format). |
|
|
70
73
|
| config | <code>object</code> | Configuration of the service. |
|
|
71
74
|
| correlationId | [<code>UUID</code>](#UUID) | CorrelationId when logging activities. |
|
|
72
75
|
|
|
73
76
|
<a name="module_api-helper..getAPIFile"></a>
|
|
74
77
|
|
|
75
78
|
### api-helper~getAPIFile(apiFilename, correlationId, options) ⇒ <code>Promise.<object></code>
|
|
76
|
-
Gets the API
|
|
79
|
+
Gets and resolves the API definition, loading from local file, Bitbucket, or SwaggerHub, and stores it in the given PATH location.
|
|
77
80
|
|
|
78
81
|
**Kind**: inner method of [<code>api-helper</code>](#module_api-helper)
|
|
79
82
|
**Returns**: <code>Promise.<object></code> - The API file itself.
|
|
80
83
|
**Category**: async
|
|
81
84
|
**Throws**:
|
|
82
85
|
|
|
83
|
-
- <code>
|
|
86
|
+
- <code>Error</code> Rejects with an error if the apiFilename resolution generates an error or the request to the API provider fails or the file cannot be saved.
|
|
84
87
|
|
|
85
88
|
`apiInfo` options has the following format:
|
|
86
89
|
``` javascript
|
|
@@ -105,14 +108,14 @@ Gets the API file from swaggerhub and stores it in the given PATH location.
|
|
|
105
108
|
<a name="module_api-helper..setupServerFiles"></a>
|
|
106
109
|
|
|
107
110
|
### api-helper~setupServerFiles(apiFilename, controllersDirectory, buildDirectory, correlationId, options) ⇒ <code>Promise.<object></code>
|
|
108
|
-
|
|
111
|
+
Sets up and validates files for the server
|
|
109
112
|
|
|
110
113
|
**Kind**: inner method of [<code>api-helper</code>](#module_api-helper)
|
|
111
114
|
**Returns**: <code>Promise.<object></code> - The API file, the API filename, the existing known security schemes and the defined security schemes.
|
|
112
115
|
**Category**: async
|
|
113
116
|
**Throws**:
|
|
114
117
|
|
|
115
|
-
- <code>
|
|
118
|
+
- <code>Error</code> Rejects with an error for many reasons associated with getAPIFile or validateSecuritySchemes or extractProperties.
|
|
116
119
|
|
|
117
120
|
**Requires**: <code>module:@mimik/request-retry</code>, <code>module:@mimik/response-helper</code>, <code>module:@mimik/sumologic-winston-logger</code>, <code>module:fs</code>, <code>module:js-yaml</code>, <code>module:path</code>
|
|
118
121
|
|
|
@@ -127,16 +130,16 @@ Setup and validates files for the server
|
|
|
127
130
|
<a name="module_api-helper..securityLib"></a>
|
|
128
131
|
|
|
129
132
|
### api-helper~securityLib(config) ⇒ <code>object</code>
|
|
130
|
-
|
|
133
|
+
Implements the security flows for the API.
|
|
131
134
|
|
|
132
135
|
**Kind**: inner method of [<code>api-helper</code>](#module_api-helper)
|
|
133
136
|
**Returns**: <code>object</code> - An object containing `SystemSecurity`, `AdminSecurity`, `UserSecurity`, and `ApiKeySecurity` handlers.
|
|
134
137
|
|
|
135
|
-
This function is used to
|
|
136
|
-
- `SystemSecurity` - used for
|
|
137
|
-
- `AdminSecurity` - used for
|
|
138
|
-
- `UserSecurity` - used for
|
|
139
|
-
- `ApiKeySecurity` - used for
|
|
138
|
+
This function is used to set up the following security handlers for the API:
|
|
139
|
+
- `SystemSecurity` - used for system-to-system operations, validates client credentials tokens.
|
|
140
|
+
- `AdminSecurity` - used for admin operations, validates admin/subAdmin client credentials tokens.
|
|
141
|
+
- `UserSecurity` - used for user operations, validates implicit flow tokens.
|
|
142
|
+
- `ApiKeySecurity` - used for API key authenticated operations, validates API keys from headers.
|
|
140
143
|
The security handlers are used to validate the tokens and scopes for the API operations.
|
|
141
144
|
**Category**: sync
|
|
142
145
|
**Requires**: <code>module:@mimik/swagger-helper</code>, <code>module:jsonwebtoken</code>
|
|
@@ -155,7 +158,7 @@ Validates the known SecuritySchemes: `SystemSecurity`, `AdminSecurity`, `UserSec
|
|
|
155
158
|
**Category**: sync
|
|
156
159
|
**Throws**:
|
|
157
160
|
|
|
158
|
-
- An error is thrown if a validation fails.
|
|
161
|
+
- <code>Error</code> An error is thrown if a validation fails.
|
|
159
162
|
|
|
160
163
|
**Requires**: <code>module:@mimik/sumologic-winston-logger</code>, <code>module:@mimik/response-helper</code>
|
|
161
164
|
|
|
@@ -167,13 +170,13 @@ Validates the known SecuritySchemes: `SystemSecurity`, `AdminSecurity`, `UserSec
|
|
|
167
170
|
<a name="module_api-helper..extractProperties"></a>
|
|
168
171
|
|
|
169
172
|
### api-helper~extractProperties(apiDefinition, controllersDirectory, buildDirectory, correlationId) ⇒ <code>void</code>
|
|
170
|
-
Extracts the properties from API definition and creates a file binding the handler with the controller operations.
|
|
173
|
+
Extracts the properties from API definition and creates a `register.js` file in the build directory binding the handler with the controller operations.
|
|
171
174
|
|
|
172
175
|
**Kind**: inner method of [<code>api-helper</code>](#module_api-helper)
|
|
173
176
|
**Category**: sync
|
|
174
177
|
**Throws**:
|
|
175
178
|
|
|
176
|
-
- An error is thrown for many reasons, like operationId does not exist in controllers, controller does not exist...
|
|
179
|
+
- <code>Error</code> An error is thrown for many reasons, like operationId does not exist in controllers, controller does not exist...
|
|
177
180
|
|
|
178
181
|
**Requires**: <code>module:@mimik/response-helper</code>, <code>module:@mimik/sumologic-winston-logger</code>, <code>module:fs</code>
|
|
179
182
|
|
package/index.js
CHANGED
|
@@ -62,7 +62,7 @@ const API_VERSION_INDEX = 2;
|
|
|
62
62
|
const POSTFIX_INDEX = 3;
|
|
63
63
|
/**
|
|
64
64
|
*
|
|
65
|
-
*
|
|
65
|
+
* Implements the security flows for the API.
|
|
66
66
|
*
|
|
67
67
|
* @function securityLib
|
|
68
68
|
* @category sync
|
|
@@ -71,37 +71,40 @@ const POSTFIX_INDEX = 3;
|
|
|
71
71
|
* @param {object} config - Configuration of the service.
|
|
72
72
|
* @return {object} An object containing `SystemSecurity`, `AdminSecurity`, `UserSecurity`, and `ApiKeySecurity` handlers.
|
|
73
73
|
*
|
|
74
|
-
* This function is used to
|
|
75
|
-
* - `SystemSecurity` - used for
|
|
76
|
-
* - `AdminSecurity` - used for
|
|
77
|
-
* - `UserSecurity` - used for
|
|
78
|
-
* - `ApiKeySecurity` - used for
|
|
74
|
+
* This function is used to set up the following security handlers for the API:
|
|
75
|
+
* - `SystemSecurity` - used for system-to-system operations, validates client credentials tokens.
|
|
76
|
+
* - `AdminSecurity` - used for admin operations, validates admin/subAdmin client credentials tokens.
|
|
77
|
+
* - `UserSecurity` - used for user operations, validates implicit flow tokens.
|
|
78
|
+
* - `ApiKeySecurity` - used for API key authenticated operations, validates API keys from headers.
|
|
79
79
|
* The security handlers are used to validate the tokens and scopes for the API operations.
|
|
80
80
|
*/
|
|
81
81
|
export { securityLib };
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
84
|
*
|
|
85
|
-
*
|
|
85
|
+
* Set up the API to be used for a service
|
|
86
86
|
*
|
|
87
87
|
* @function apiSetup
|
|
88
88
|
* @category async
|
|
89
89
|
* @requires @mimik/response-helper
|
|
90
90
|
* @requires @mimik/sumologic-winston-logger
|
|
91
91
|
* @requires openapi-backend
|
|
92
|
-
* @param {object} setup -
|
|
93
|
-
* @param {
|
|
94
|
-
* @param {
|
|
95
|
-
* @param {
|
|
92
|
+
* @param {object} setup - Object containing the apiFilename and the existing security schemes in the API definition.
|
|
93
|
+
* @param {PATH} setup.apiFilename - Path to the resolved API definition file.
|
|
94
|
+
* @param {Array.<string>} setup.existingSecuritySchemes - Known security scheme names present in the API definition.
|
|
95
|
+
* @param {Array.<string>} setup.definedSecuritySchemes - All security scheme names defined in the API definition.
|
|
96
|
+
* @param {object} registeredOperations - Map of operationId to handler function to register for the API.
|
|
97
|
+
* @param {object} securityHandlers - Map of security scheme name to handler object to add for the service.
|
|
98
|
+
* @param {object} extraFormats - Map of format name to format definition for validating properties. Each entry is either an empty object (to use a built-in ajv-formats format) or an object with `type` and `validate` properties (to define a custom format).
|
|
96
99
|
* @param {object} config - Configuration of the service.
|
|
97
100
|
* @param {UUID} correlationId - CorrelationId when logging activities.
|
|
98
|
-
* @return {Promise.<object>} The
|
|
99
|
-
* @throws {
|
|
101
|
+
* @return {Promise.<object>} The initialized OpenAPIBackend instance.
|
|
102
|
+
* @throws {Error} Rejects with an error if the initialization failed.
|
|
100
103
|
*
|
|
101
104
|
* The following scheme names are reserved: `SystemSecurity`, `AdminSecurity`, `UserSecurity`, `PeerSecurity`, `ApiKeySecurity`.
|
|
102
105
|
* The following security schemes can be defaulted: `SystemSecurity`, `AdminSecurity`, `UserSecurity`, `ApiKeySecurity`.
|
|
103
106
|
* The secOptions in the options property passed when using `init` allows the following operations:
|
|
104
|
-
* - introduce a
|
|
107
|
+
* - introduce a custom security scheme, in this case secOptions contains: { newSecurityScheme: {function}newSecurityHandler },
|
|
105
108
|
* - disable a security scheme that is defined in the swagger API, in this case secOptions contains: { securitySchemeToDisable: { {boolean}notEnabled: true } },
|
|
106
109
|
* - overwrite an existing security scheme, in this case secOptions contains: { securitySchemeToOverwrite: {function}newSecurityHandler }.
|
|
107
110
|
* If the secOptions is not present either to introduce, disable or overwrite a security scheme that is present in the swagger API file an error is generated.
|
|
@@ -132,7 +135,7 @@ export const apiSetup = (setup, registeredOperations, securityHandlers, extraFor
|
|
|
132
135
|
let mode;
|
|
133
136
|
|
|
134
137
|
api.register(registeredOperations);
|
|
135
|
-
if (config
|
|
138
|
+
if (config.nodeEnvironment.toLowerCase() !== LOCAL || config.serverSettings.securitySet === SET_ON) {
|
|
136
139
|
mode = SECURITY_ON;
|
|
137
140
|
}
|
|
138
141
|
else {
|
|
@@ -160,7 +163,7 @@ export const apiSetup = (setup, registeredOperations, securityHandlers, extraFor
|
|
|
160
163
|
if (unusedSecuritySchemes.length !== EMPTY) throw getRichError('System', 'unused handlers for security schemes', { unusedSecuritySchemes });
|
|
161
164
|
|
|
162
165
|
remainingSecurities.forEach((securityScheme) => {
|
|
163
|
-
if (!securityHandlerNames.includes(securityScheme)
|
|
166
|
+
if (!securityHandlerNames.includes(securityScheme)) {
|
|
164
167
|
throw getRichError('System', 'missing handler for security scheme', { securityScheme });
|
|
165
168
|
}
|
|
166
169
|
});
|
|
@@ -173,7 +176,7 @@ export const apiSetup = (setup, registeredOperations, securityHandlers, extraFor
|
|
|
173
176
|
else if (remainingSecurities.length !== EMPTY) throw getRichError('System', 'missing handlers for security schemes', { missingSecuritySchemes: remainingSecurities });
|
|
174
177
|
return api.init()
|
|
175
178
|
.catch((err) => {
|
|
176
|
-
throw getRichError('System', 'could not initialize the api', {
|
|
179
|
+
throw getRichError('System', 'could not initialize the api', { apiFilename }, err);
|
|
177
180
|
})
|
|
178
181
|
.then(() => api);
|
|
179
182
|
};
|
|
@@ -236,7 +239,7 @@ const buildProviderRequest = (params, apiInfo, apiFilename) => {
|
|
|
236
239
|
|
|
237
240
|
/**
|
|
238
241
|
*
|
|
239
|
-
* Gets the API
|
|
242
|
+
* Gets and resolves the API definition, loading from local file, Bitbucket, or SwaggerHub, and stores it in the given PATH location.
|
|
240
243
|
*
|
|
241
244
|
* @function getAPIFile
|
|
242
245
|
* @category async
|
|
@@ -246,11 +249,11 @@ const buildProviderRequest = (params, apiInfo, apiFilename) => {
|
|
|
246
249
|
* @requires fs
|
|
247
250
|
* @requires js-yaml
|
|
248
251
|
* @requires path
|
|
249
|
-
* @param {PATH} apiFilename -
|
|
252
|
+
* @param {PATH} apiFilename - Name of the file where the API file will be stored.
|
|
250
253
|
* @param {UUID} correlationId - CorrelationId when logging activities.
|
|
251
254
|
* @param {object} options - Options associated with the call. Use to pass `metrics` to `rpRetry` and `apiInfo` to access the api file in the api provider.
|
|
252
255
|
* @return {Promise.<object>} The API file itself.
|
|
253
|
-
* @throws {
|
|
256
|
+
* @throws {Error} Rejects with an error if the apiFilename resolution generates an error or the request to the API provider fails or the file cannot be saved.
|
|
254
257
|
*
|
|
255
258
|
* `apiInfo` options has the following format:
|
|
256
259
|
* ``` javascript
|
|
@@ -378,7 +381,7 @@ export const getAPIFile = (apiFilename, correlationId, options) => {
|
|
|
378
381
|
* @param {object} apiDefinition - JSON object containing the API definition.
|
|
379
382
|
* @param {UUID} correlationId - CorrelationId when logging activities.
|
|
380
383
|
* @return {Array.<string>} An array of the known securitySchemes that are in the API definition.
|
|
381
|
-
* @throws An error is thrown if a validation fails.
|
|
384
|
+
* @throws {Error} An error is thrown if a validation fails.
|
|
382
385
|
*/
|
|
383
386
|
export const validateSecuritySchemes = (apiDefinition, correlationId) => {
|
|
384
387
|
const existingSecuritySchemes = [];
|
|
@@ -398,7 +401,7 @@ export const validateSecuritySchemes = (apiDefinition, correlationId) => {
|
|
|
398
401
|
|
|
399
402
|
/**
|
|
400
403
|
*
|
|
401
|
-
* Extracts the properties from API definition and creates a file binding the handler with the controller operations.
|
|
404
|
+
* Extracts the properties from API definition and creates a `register.js` file in the build directory binding the handler with the controller operations.
|
|
402
405
|
*
|
|
403
406
|
* @function extractProperties
|
|
404
407
|
* @category sync
|
|
@@ -410,7 +413,7 @@ export const validateSecuritySchemes = (apiDefinition, correlationId) => {
|
|
|
410
413
|
* @param {PATH} buildDirectory - Directory where the register file will be stored.
|
|
411
414
|
* @param {UUID} correlationId - CorrelationId when logging activities.
|
|
412
415
|
* @return {void}
|
|
413
|
-
* @throws An error is thrown for many reasons, like operationId does not exist in controllers, controller does not exist...
|
|
416
|
+
* @throws {Error} An error is thrown for many reasons, like operationId does not exist in controllers, controller does not exist...
|
|
414
417
|
*/
|
|
415
418
|
export const extractProperties = (apiDefinition, controllersDirectory, buildDirectory, correlationId) => {
|
|
416
419
|
const result = {};
|
|
@@ -455,17 +458,19 @@ export const extractProperties = (apiDefinition, controllersDirectory, buildDire
|
|
|
455
458
|
catch (err) {
|
|
456
459
|
throw getRichError('System', 'file system error', { controllerFilename }, err);
|
|
457
460
|
}
|
|
461
|
+
let file;
|
|
462
|
+
|
|
458
463
|
try {
|
|
459
|
-
|
|
460
|
-
if (!file.includes(`${operation.operationId},`)
|
|
461
|
-
&& !file.includes(`${operation.operationId}:`)
|
|
462
|
-
&& !file.includes(`export ${operation.operationId}`)) { // code must be linted before
|
|
463
|
-
throw getRichError('System', 'missing operationId in controller file', { controllerFilename, operationId: operation.operationId });
|
|
464
|
-
}
|
|
464
|
+
file = fs.readFileSync(controllerFilename, 'utf8');
|
|
465
465
|
}
|
|
466
466
|
catch (err) {
|
|
467
467
|
throw getRichError('System', 'file system error', { controllerFilename, operationId: operation.operationId }, err);
|
|
468
468
|
}
|
|
469
|
+
if (!file.includes(`${operation.operationId},`)
|
|
470
|
+
&& !file.includes(`${operation.operationId}:`)
|
|
471
|
+
&& !file.includes(`export ${operation.operationId}`)) { // code must be linted before
|
|
472
|
+
throw getRichError('System', 'missing operationId in controller file', { controllerFilename, operationId: operation.operationId });
|
|
473
|
+
}
|
|
469
474
|
if (result[controller]) result[controller].push(operation.operationId);
|
|
470
475
|
else result[controller] = [operation.operationId];
|
|
471
476
|
}
|
|
@@ -481,7 +486,7 @@ export const extractProperties = (apiDefinition, controllersDirectory, buildDire
|
|
|
481
486
|
|
|
482
487
|
/**
|
|
483
488
|
*
|
|
484
|
-
*
|
|
489
|
+
* Sets up and validates files for the server
|
|
485
490
|
*
|
|
486
491
|
* @function setupServerFiles
|
|
487
492
|
* @category async
|
|
@@ -491,13 +496,13 @@ export const extractProperties = (apiDefinition, controllersDirectory, buildDire
|
|
|
491
496
|
* @requires fs
|
|
492
497
|
* @requires js-yaml
|
|
493
498
|
* @requires path
|
|
494
|
-
* @param {PATH} apiFilename -
|
|
499
|
+
* @param {PATH} apiFilename - Name of the file where the API file will be stored.
|
|
495
500
|
* @param {PATH} controllersDirectory - Directory to find the controller files.
|
|
496
501
|
* @param {PATH} buildDirectory - Directory where the register file will be stored.
|
|
497
502
|
* @param {UUID} correlationId - CorrelationId when logging activities.
|
|
498
503
|
* @param {object} options - Options associated with the call. Use to pass `metrics` to `rpRetry` and `apiKey` to access private API.
|
|
499
504
|
* @return {Promise.<object>} The API file, the API filename, the existing known security schemes and the defined security schemes.
|
|
500
|
-
* @throws {
|
|
505
|
+
* @throws {Error} Rejects with an error for many reasons associated with getAPIFile or validateSecuritySchemes or extractProperties.
|
|
501
506
|
*/
|
|
502
507
|
export const setupServerFiles = (apiFilename, controllersDirectory, buildDirectory, correlationId, options) => getAPIFile(apiFilename, correlationId, options)
|
|
503
508
|
.then((apiDefinition) => {
|
package/lib/baseHandlers.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
+
import { ERROR_CODE } from '@mimik/response-helper';
|
|
1
2
|
import { rejectRequest } from '@mimik/swagger-helper';
|
|
2
3
|
|
|
3
|
-
const PARAMETER_ERROR = 400;
|
|
4
|
-
const NOT_FOUND_ERROR = 404;
|
|
5
|
-
const UNAUTHORIZED_ERROR = 401;
|
|
6
|
-
const NOT_IMPLEMENTED_ERROR = 501;
|
|
7
|
-
|
|
8
4
|
const validationFail = (con, req, res) => {
|
|
9
5
|
const error = new Error('Failed schema validation');
|
|
10
6
|
|
|
11
|
-
error.statusCode =
|
|
7
|
+
error.statusCode = ERROR_CODE.PARAMETER;
|
|
12
8
|
error.info = {
|
|
13
9
|
method: req.method,
|
|
14
10
|
path: req.url,
|
|
@@ -22,7 +18,7 @@ const notFound = (con, req, res) => {
|
|
|
22
18
|
const path = req.url;
|
|
23
19
|
const error = new Error(`path ${path} not defined in Swagger specification`);
|
|
24
20
|
|
|
25
|
-
error.statusCode =
|
|
21
|
+
error.statusCode = ERROR_CODE.NOT_FOUND;
|
|
26
22
|
error.info = {
|
|
27
23
|
method: req.method,
|
|
28
24
|
path,
|
|
@@ -33,7 +29,7 @@ const notFound = (con, req, res) => {
|
|
|
33
29
|
const unauthorizedHandler = (con, req, res) => {
|
|
34
30
|
let error = new Error('Unauthorized');
|
|
35
31
|
|
|
36
|
-
error.statusCode =
|
|
32
|
+
error.statusCode = ERROR_CODE.UNAUTHORIZED;
|
|
37
33
|
const schemes = Object.keys(con.security).filter(key => key !== 'authorized');
|
|
38
34
|
|
|
39
35
|
schemes.forEach((scheme) => {
|
|
@@ -50,7 +46,7 @@ const notImplemented = (con, req, res) => {
|
|
|
50
46
|
const path = req.url;
|
|
51
47
|
const error = new Error(`${method} ${path} defined in Swagger specification, but not implemented`);
|
|
52
48
|
|
|
53
|
-
error.statusCode =
|
|
49
|
+
error.statusCode = ERROR_CODE.NOT_IMPLEMENTED;
|
|
54
50
|
error.info = {
|
|
55
51
|
method,
|
|
56
52
|
path,
|
|
@@ -64,7 +60,7 @@ const methodNotAllowed = (con, req, res) => {
|
|
|
64
60
|
const path = req.url;
|
|
65
61
|
const error = new Error(`path ${path} defined in Swagger specification, but the method ${method} is not defined`);
|
|
66
62
|
|
|
67
|
-
error.statusCode =
|
|
63
|
+
error.statusCode = ERROR_CODE.NOT_ALLOWED;
|
|
68
64
|
error.info = {
|
|
69
65
|
method,
|
|
70
66
|
path,
|
|
@@ -72,24 +68,10 @@ const methodNotAllowed = (con, req, res) => {
|
|
|
72
68
|
rejectRequest(error, con, res);
|
|
73
69
|
};
|
|
74
70
|
|
|
75
|
-
/*
|
|
76
|
-
const postResponseHandler = (con, req, res) => {
|
|
77
|
-
const valid = con.api.validateResponse(con.response, con.operation);
|
|
78
|
-
console.log('----->', con.response);
|
|
79
|
-
console.log('----->', valid);
|
|
80
|
-
if (valid.errors) {
|
|
81
|
-
// response validation failed
|
|
82
|
-
return res.status(502).json({ status: 502, err: valid.errors });
|
|
83
|
-
}
|
|
84
|
-
return res.status(200).json(con.response);
|
|
85
|
-
};
|
|
86
|
-
*/
|
|
87
|
-
|
|
88
71
|
export default {
|
|
89
72
|
validationFail,
|
|
90
73
|
notFound,
|
|
91
74
|
unauthorizedHandler,
|
|
92
75
|
notImplemented,
|
|
93
76
|
methodNotAllowed,
|
|
94
|
-
// postResponseHandler,
|
|
95
77
|
};
|
package/lib/common.js
CHANGED
|
@@ -50,7 +50,7 @@ const CLAIMS_SEPARATOR = ',';
|
|
|
50
50
|
const BEARERS = ['bearer', 'Bearer'];
|
|
51
51
|
const USER = 'user';
|
|
52
52
|
const CLUSTER = 'cluster';
|
|
53
|
-
const ESLINT_HEAD = '/* eslint sort-imports:
|
|
53
|
+
const ESLINT_HEAD = '/* eslint sort-imports: off */\n';
|
|
54
54
|
|
|
55
55
|
export {
|
|
56
56
|
X_ROUTER_CONTROLLER,
|
package/lib/extract-helper.js
CHANGED
|
@@ -25,23 +25,18 @@ const saveProperties = (extractResult, buildDirectory, controllersDirectoryName,
|
|
|
25
25
|
}
|
|
26
26
|
const controllers = Object.keys(extractResult);
|
|
27
27
|
const operationIds = [];
|
|
28
|
-
|
|
29
|
-
let itemToSave;
|
|
28
|
+
const imports = [];
|
|
30
29
|
|
|
31
30
|
controllers.forEach((controller) => {
|
|
32
|
-
|
|
33
|
-
extractResult[controller].forEach((operationId) => {
|
|
34
|
-
itemToSave += ` ${operationId},\n`;
|
|
31
|
+
const items = extractResult[controller].map((operationId) => {
|
|
35
32
|
operationIds.push(operationId);
|
|
33
|
+
return ` ${operationId},`;
|
|
36
34
|
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
stringToSave += '\nexport {\n';
|
|
40
|
-
itemToSave = '';
|
|
41
|
-
operationIds.forEach((operationId) => {
|
|
42
|
-
itemToSave += ` ${operationId},\n`;
|
|
35
|
+
|
|
36
|
+
imports.push(`import {\n${items.join('\n')}\n} from '../${controllersDirectoryName}/${controller}${EXTENSION}';`);
|
|
43
37
|
});
|
|
44
|
-
|
|
38
|
+
const exportLines = operationIds.map(id => ` ${id},\n`).join('');
|
|
39
|
+
const stringToSave = `${ESLINT_HEAD}${imports.join('\n')}\n\nexport {\n${exportLines}};\n`;
|
|
45
40
|
logger.info(`creating ${filename}`, { filename }, correlationId);
|
|
46
41
|
try {
|
|
47
42
|
fs.writeFileSync(filename, stringToSave);
|
|
@@ -28,10 +28,10 @@ const validateApiKey = (securitySchemes, securityType) => {
|
|
|
28
28
|
|
|
29
29
|
if (security) {
|
|
30
30
|
if (security.in !== API_KEY_IN) {
|
|
31
|
-
throw getRichError('System', `
|
|
31
|
+
throw getRichError('System', `API key security must be in ${API_KEY_IN}`, { securityType, receivedIn: security.in, expectedIn: API_KEY_IN });
|
|
32
32
|
}
|
|
33
33
|
if (security.name !== API_KEY_NAME) {
|
|
34
|
-
throw getRichError('System', `
|
|
34
|
+
throw getRichError('System', `API key security must be named ${API_KEY_NAME}`, { securityType, receivedName: security.name, expectedName: API_KEY_NAME });
|
|
35
35
|
}
|
|
36
36
|
return securityType;
|
|
37
37
|
}
|
package/lib/securityHandlers.js
CHANGED
|
@@ -36,14 +36,7 @@ const SCOPE_INDEX = 0;
|
|
|
36
36
|
const CLAIMS_INDEX = 1;
|
|
37
37
|
const RESOURCE_INDEX = 0;
|
|
38
38
|
|
|
39
|
-
const getScopes = (conf, securityType) =>
|
|
40
|
-
let scopes = [];
|
|
41
|
-
|
|
42
|
-
conf.operation.security.forEach((security) => {
|
|
43
|
-
if (security[securityType]) scopes = scopes.concat(security[securityType]);
|
|
44
|
-
});
|
|
45
|
-
return scopes;
|
|
46
|
-
};
|
|
39
|
+
const getScopes = (conf, securityType) => conf.operation.security.flatMap(security => security[securityType] || []);
|
|
47
40
|
|
|
48
41
|
const getError = (message, statusCode) => {
|
|
49
42
|
const error = new Error(message);
|
|
@@ -53,15 +46,8 @@ const getError = (message, statusCode) => {
|
|
|
53
46
|
};
|
|
54
47
|
|
|
55
48
|
const checkToken = (authToken) => {
|
|
56
|
-
|
|
49
|
+
const token = jwt.decode(authToken);
|
|
57
50
|
|
|
58
|
-
try {
|
|
59
|
-
token = jwt.decode(authToken);
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
err.statusCode = UNAUTHORIZED_ERROR;
|
|
63
|
-
throw err;
|
|
64
|
-
}
|
|
65
51
|
if (!token) {
|
|
66
52
|
throw getError('invalid token', UNAUTHORIZED_ERROR);
|
|
67
53
|
}
|
|
@@ -93,17 +79,17 @@ const checkScopes = (tokenScopes, defScopes, definition) => {
|
|
|
93
79
|
if (!tokenScopes) {
|
|
94
80
|
throw getError('no scope in authorization token', UNAUTHORIZED_ERROR);
|
|
95
81
|
}
|
|
96
|
-
|
|
82
|
+
const claims = [];
|
|
97
83
|
let onBehalf = false;
|
|
98
84
|
|
|
99
85
|
if (defScopes && defScopes.length !== EMPTY) {
|
|
100
86
|
const currentScopes = tokenScopes.split(SCOPES_SEPARATOR);
|
|
101
87
|
const intersects = [];
|
|
102
|
-
let resourceIndex = FIRST;
|
|
103
88
|
|
|
104
89
|
currentScopes.forEach((currentScope) => {
|
|
105
90
|
const analyzedScope = currentScope.split(SCOPE_CLAIMS_SEPARATOR);
|
|
106
91
|
const analyzedResource = analyzedScope[SCOPE_INDEX].split(RESOURCE_SEPARATOR);
|
|
92
|
+
let resourceIndex = FIRST;
|
|
107
93
|
|
|
108
94
|
if (analyzedResource[RESOURCE_INDEX] === ON_BEHALF) {
|
|
109
95
|
onBehalf = true;
|
|
@@ -129,7 +115,7 @@ const checkScopes = (tokenScopes, defScopes, definition) => {
|
|
|
129
115
|
if (claimsIntersects.length !== includedClaims.length) {
|
|
130
116
|
throw getError(`incorrect claims included: ${includedClaims.filter(cla => !claimsIntersects.includes(cla))}`, FORBIDDEN_ERROR);
|
|
131
117
|
}
|
|
132
|
-
claims
|
|
118
|
+
claims.push(...claimsIntersects);
|
|
133
119
|
}
|
|
134
120
|
intersects.push(analyzedScope[SCOPE_INDEX]);
|
|
135
121
|
}
|
|
@@ -141,13 +127,26 @@ const checkScopes = (tokenScopes, defScopes, definition) => {
|
|
|
141
127
|
return { onBehalf, claims };
|
|
142
128
|
};
|
|
143
129
|
|
|
130
|
+
const setParam = (req, request, key, value) => {
|
|
131
|
+
req[key] = value;
|
|
132
|
+
request[key] = value;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const setParams = (req, request, params) => {
|
|
136
|
+
Object.keys(params).forEach(key => setParam(req, request, key, params[key]));
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const createMockHandler = params => (con, req) => {
|
|
140
|
+
setParams(req, con.request, params);
|
|
141
|
+
return true;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
144
|
export const securityLib = (config) => {
|
|
145
145
|
const verifyTokenClientCredentials = (authToken) => {
|
|
146
146
|
const { server, generic } = config.security;
|
|
147
147
|
const options = {
|
|
148
148
|
audience: (generic.audience === NO_GENERIC) ? server.audience : generic.audience,
|
|
149
149
|
issuer: server.issuer,
|
|
150
|
-
// subject: `${config.serverSettings.id}@clients`,
|
|
151
150
|
};
|
|
152
151
|
|
|
153
152
|
try {
|
|
@@ -186,19 +185,24 @@ export const securityLib = (config) => {
|
|
|
186
185
|
}
|
|
187
186
|
};
|
|
188
187
|
|
|
188
|
+
const setClientParams = (req, request, token, scopeResult) => {
|
|
189
|
+
setParam(req, request, TOKEN_PARAMS.claims, scopeResult.claims);
|
|
190
|
+
if (scopeResult.onBehalf) setParam(req, request, TOKEN_PARAMS.onBehalf, true);
|
|
191
|
+
if (token.subType) setParam(req, request, TOKEN_PARAMS.tokenType, token.subType);
|
|
192
|
+
if (token.sub) setParam(req, request, TOKEN_PARAMS.clientId, token.sub);
|
|
193
|
+
if (token.cust) setParam(req, request, TOKEN_PARAMS.customer, token.cust);
|
|
194
|
+
};
|
|
195
|
+
|
|
189
196
|
const AdminSecurity = {
|
|
190
197
|
regular: (con, req) => {
|
|
191
198
|
const authToken = checkHeaders(req.headers);
|
|
192
199
|
const token = checkToken(authToken);
|
|
193
|
-
const { request } = con;
|
|
194
200
|
|
|
195
201
|
if (token.subType !== ADMIN && token.subType !== SUB_ADMIN) {
|
|
196
202
|
throw getError('invalid token: wrong type', FORBIDDEN_ERROR);
|
|
197
203
|
}
|
|
198
204
|
if (token.subType === SUB_ADMIN) {
|
|
199
|
-
if (!token.cust)
|
|
200
|
-
throw getError('invalid token: no customer', FORBIDDEN_ERROR);
|
|
201
|
-
}
|
|
205
|
+
if (!token.cust) throw getError('invalid token: no customer', FORBIDDEN_ERROR);
|
|
202
206
|
}
|
|
203
207
|
else if (token.sub !== `${config.security.admin.externalId}${CLIENT}`) {
|
|
204
208
|
throw getError(`jwt subject invalid: ${token.sub}`, FORBIDDEN_ERROR);
|
|
@@ -206,42 +210,21 @@ export const securityLib = (config) => {
|
|
|
206
210
|
verifyTokenClientCredentials(authToken);
|
|
207
211
|
const scopeResult = checkScopes(token.scope, getScopes(con, ADMIN_SECURITY), con.api.definition);
|
|
208
212
|
|
|
209
|
-
req
|
|
210
|
-
request[TOKEN_PARAMS.claims] = scopeResult.claims;
|
|
211
|
-
if (token.subType) {
|
|
212
|
-
req[TOKEN_PARAMS.tokenType] = token.subType;
|
|
213
|
-
request[TOKEN_PARAMS.tokenType] = token.subType;
|
|
214
|
-
}
|
|
215
|
-
if (token.sub) {
|
|
216
|
-
req[TOKEN_PARAMS.clientId] = token.sub;
|
|
217
|
-
request[TOKEN_PARAMS.clientId] = token.sub;
|
|
218
|
-
}
|
|
219
|
-
if (token.cust) {
|
|
220
|
-
req[TOKEN_PARAMS.customer] = token.cust;
|
|
221
|
-
request[TOKEN_PARAMS.customer] = token.cust;
|
|
222
|
-
}
|
|
223
|
-
return true;
|
|
224
|
-
},
|
|
225
|
-
mock: (con, req) => {
|
|
226
|
-
const { request } = con;
|
|
227
|
-
|
|
228
|
-
req[TOKEN_PARAMS.claims] = ['dummyClaims'];
|
|
229
|
-
req[TOKEN_PARAMS.tokenType] = ADMIN;
|
|
230
|
-
req[TOKEN_PARAMS.clientId] = 'dummyClientId';
|
|
231
|
-
req[TOKEN_PARAMS.customer] = 'dummyCustomer';
|
|
232
|
-
request[TOKEN_PARAMS.claims] = ['dummyClaims'];
|
|
233
|
-
request[TOKEN_PARAMS.tokenType] = ADMIN;
|
|
234
|
-
request[TOKEN_PARAMS.clientId] = 'dummyClientId';
|
|
235
|
-
request[TOKEN_PARAMS.customer] = 'dummyCustomer';
|
|
213
|
+
setClientParams(req, con.request, token, scopeResult);
|
|
236
214
|
return true;
|
|
237
215
|
},
|
|
216
|
+
mock: createMockHandler({
|
|
217
|
+
[TOKEN_PARAMS.claims]: ['dummyClaims'],
|
|
218
|
+
[TOKEN_PARAMS.tokenType]: ADMIN,
|
|
219
|
+
[TOKEN_PARAMS.clientId]: 'dummyClientId',
|
|
220
|
+
[TOKEN_PARAMS.customer]: 'dummyCustomer',
|
|
221
|
+
}),
|
|
238
222
|
};
|
|
239
223
|
|
|
240
224
|
const SystemSecurity = {
|
|
241
225
|
regular: (con, req) => {
|
|
242
226
|
const authToken = checkHeaders(req.headers);
|
|
243
227
|
const token = checkToken(authToken);
|
|
244
|
-
const { request } = con;
|
|
245
228
|
|
|
246
229
|
if (token.subType === ADMIN || token.subType === SUB_ADMIN) {
|
|
247
230
|
throw getError('invalid token: wrong type', FORBIDDEN_ERROR);
|
|
@@ -249,112 +232,56 @@ export const securityLib = (config) => {
|
|
|
249
232
|
verifyTokenClientCredentials(authToken);
|
|
250
233
|
const scopeResult = checkScopes(token.scope, getScopes(con, SYSTEM_SECURITY), con.api.definition);
|
|
251
234
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
request[TOKEN_PARAMS.onBehalf] = true;
|
|
255
|
-
}
|
|
256
|
-
req[TOKEN_PARAMS.claims] = scopeResult.claims;
|
|
257
|
-
request[TOKEN_PARAMS.claims] = scopeResult.claims;
|
|
258
|
-
if (token.subType) {
|
|
259
|
-
req[TOKEN_PARAMS.tokenType] = token.subType;
|
|
260
|
-
request[TOKEN_PARAMS.tokenType] = token.subType;
|
|
261
|
-
}
|
|
262
|
-
if (token.sub) {
|
|
263
|
-
req[TOKEN_PARAMS.clientId] = token.sub;
|
|
264
|
-
request[TOKEN_PARAMS.clientId] = token.sub;
|
|
265
|
-
}
|
|
266
|
-
if (token.cust) {
|
|
267
|
-
req[TOKEN_PARAMS.customer] = token.cust;
|
|
268
|
-
request[TOKEN_PARAMS.customer] = token.cust;
|
|
269
|
-
}
|
|
270
|
-
if (token.type === CLUSTER) {
|
|
271
|
-
req[TOKEN_PARAMS.cluster] = true;
|
|
272
|
-
request[TOKEN_PARAMS.cluster] = true;
|
|
273
|
-
}
|
|
274
|
-
return true;
|
|
275
|
-
},
|
|
276
|
-
mock: (con, req) => {
|
|
277
|
-
const { request } = con;
|
|
278
|
-
|
|
279
|
-
req[TOKEN_PARAMS.claims] = ['dummyClaims'];
|
|
280
|
-
req[TOKEN_PARAMS.tokenType] = 'dummyServiceType';
|
|
281
|
-
req[TOKEN_PARAMS.clientId] = 'dummyClientId';
|
|
282
|
-
req[TOKEN_PARAMS.customer] = 'dummyCustomer';
|
|
283
|
-
request[TOKEN_PARAMS.claims] = ['dummyClaims'];
|
|
284
|
-
request[TOKEN_PARAMS.tokenType] = 'dummyServiceType';
|
|
285
|
-
request[TOKEN_PARAMS.clientId] = 'dummyClientId';
|
|
286
|
-
request[TOKEN_PARAMS.customer] = 'dummyCustomer';
|
|
235
|
+
setClientParams(req, con.request, token, scopeResult);
|
|
236
|
+
if (token.type === CLUSTER) setParam(req, con.request, TOKEN_PARAMS.cluster, true);
|
|
287
237
|
return true;
|
|
288
238
|
},
|
|
239
|
+
mock: createMockHandler({
|
|
240
|
+
[TOKEN_PARAMS.claims]: ['dummyClaims'],
|
|
241
|
+
[TOKEN_PARAMS.tokenType]: 'dummyServiceType',
|
|
242
|
+
[TOKEN_PARAMS.clientId]: 'dummyClientId',
|
|
243
|
+
[TOKEN_PARAMS.customer]: 'dummyCustomer',
|
|
244
|
+
}),
|
|
289
245
|
};
|
|
290
246
|
|
|
291
247
|
const UserSecurity = {
|
|
292
248
|
regular: (con, req) => {
|
|
293
249
|
const authToken = checkHeaders(req.headers);
|
|
294
250
|
const token = checkToken(authToken);
|
|
295
|
-
const { request } = con;
|
|
296
251
|
|
|
297
252
|
verifyTokenImplicit(authToken);
|
|
298
253
|
const scopeResult = checkScopes(token.scope, getScopes(con, USER_SECURITY), con.api.definition);
|
|
299
254
|
|
|
300
|
-
if (scopeResult.onBehalf)
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
req
|
|
305
|
-
request[TOKEN_PARAMS.claims] = scopeResult.claims;
|
|
306
|
-
req[TOKEN_PARAMS.tokenType] = USER;
|
|
307
|
-
request[TOKEN_PARAMS.tokenType] = USER;
|
|
308
|
-
if (token.sub) {
|
|
309
|
-
req[TOKEN_PARAMS.userId] = token.sub;
|
|
310
|
-
request[TOKEN_PARAMS.userId] = token.sub;
|
|
311
|
-
}
|
|
312
|
-
if (token.azp) {
|
|
313
|
-
req[TOKEN_PARAMS.appId] = token.azp;
|
|
314
|
-
request[TOKEN_PARAMS.appId] = token.azp;
|
|
315
|
-
}
|
|
255
|
+
if (scopeResult.onBehalf) setParam(req, con.request, TOKEN_PARAMS.onBehalf, true);
|
|
256
|
+
setParam(req, con.request, TOKEN_PARAMS.claims, scopeResult.claims);
|
|
257
|
+
setParam(req, con.request, TOKEN_PARAMS.tokenType, USER);
|
|
258
|
+
if (token.sub) setParam(req, con.request, TOKEN_PARAMS.userId, token.sub);
|
|
259
|
+
if (token.azp) setParam(req, con.request, TOKEN_PARAMS.appId, token.azp);
|
|
316
260
|
if (token.may_act && token.may_act.sub) {
|
|
317
|
-
req
|
|
318
|
-
request
|
|
319
|
-
req[TOKEN_PARAMS.userId] = token.may_act.sub;
|
|
320
|
-
request[TOKEN_PARAMS.userId] = token.may_act.sub;
|
|
261
|
+
setParam(req, con.request, TOKEN_PARAMS.onBehalfId, token.sub);
|
|
262
|
+
setParam(req, con.request, TOKEN_PARAMS.userId, token.may_act.sub);
|
|
321
263
|
}
|
|
322
264
|
return true;
|
|
323
265
|
},
|
|
324
|
-
mock: (
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
req[TOKEN_PARAMS.tokenType] = USER;
|
|
331
|
-
request[TOKEN_PARAMS.claims] = ['dummyClaims'];
|
|
332
|
-
request[TOKEN_PARAMS.userId] = 'dummyUserId';
|
|
333
|
-
request[TOKEN_PARAMS.appId] = 'dummyAppId';
|
|
334
|
-
request[TOKEN_PARAMS.tokenType] = USER;
|
|
335
|
-
return true;
|
|
336
|
-
},
|
|
266
|
+
mock: createMockHandler({
|
|
267
|
+
[TOKEN_PARAMS.claims]: ['dummyClaims'],
|
|
268
|
+
[TOKEN_PARAMS.userId]: 'dummyUserId',
|
|
269
|
+
[TOKEN_PARAMS.appId]: 'dummyAppId',
|
|
270
|
+
[TOKEN_PARAMS.tokenType]: USER,
|
|
271
|
+
}),
|
|
337
272
|
};
|
|
338
273
|
|
|
339
274
|
const ApiKeySecurity = {
|
|
340
275
|
regular: (con, req) => {
|
|
341
276
|
const apiKey = req.headers ? req.headers[API_KEY_NAME.toLowerCase()] : null;
|
|
342
|
-
const { request } = con;
|
|
343
277
|
|
|
344
|
-
if (config.security.apiKeys.includes(apiKey)) {
|
|
345
|
-
req
|
|
346
|
-
request[API_KEY_NAME] = apiKey;
|
|
278
|
+
if (config.security.apiKeys && config.security.apiKeys.includes(apiKey)) {
|
|
279
|
+
setParam(req, con.request, API_KEY_NAME, apiKey);
|
|
347
280
|
return true;
|
|
348
281
|
}
|
|
349
282
|
throw getError('invalid API key', UNAUTHORIZED_ERROR);
|
|
350
283
|
},
|
|
351
|
-
mock: (
|
|
352
|
-
const { request } = con;
|
|
353
|
-
|
|
354
|
-
req[API_KEY_NAME] = 'dummyApiKey';
|
|
355
|
-
request[API_KEY_NAME] = 'dummyApiKey';
|
|
356
|
-
return true;
|
|
357
|
-
},
|
|
284
|
+
mock: createMockHandler({ [API_KEY_NAME]: 'dummyApiKey' }),
|
|
358
285
|
};
|
|
359
286
|
|
|
360
287
|
return {
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mimik/api-helper",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "helper for openAPI backend and mimik service",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"exports": "./index.js",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=24.0.0"
|
|
10
|
+
},
|
|
7
11
|
"scripts": {
|
|
8
12
|
"lint": "eslint . --no-error-on-unmatched-pattern",
|
|
9
13
|
"docs": "jsdoc2md index.js > README.md",
|
|
10
|
-
"test": "mocha
|
|
11
|
-
"test-ci": "c8
|
|
14
|
+
"test": "mocha",
|
|
15
|
+
"test-ci": "c8 npm test",
|
|
12
16
|
"prepublishOnly": "npm run docs && npm run lint && npm run test-ci",
|
|
13
17
|
"commit-ready": "npm run docs && npm run lint && npm run test-ci"
|
|
14
18
|
},
|
|
@@ -19,33 +23,31 @@
|
|
|
19
23
|
],
|
|
20
24
|
"author": "mimik technology inc <support@mimik.com> (https://developer.mimik.com/)",
|
|
21
25
|
"license": "MIT",
|
|
22
|
-
"engines": {
|
|
23
|
-
"node": ">=24"
|
|
24
|
-
},
|
|
25
26
|
"repository": {
|
|
26
27
|
"type": "git",
|
|
27
28
|
"url": "https://bitbucket.org/mimiktech/api-helper"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
|
-
"@mimik/request-retry": "^4.0.
|
|
31
|
-
"@mimik/response-helper": "^4.0.
|
|
32
|
-
"@mimik/sumologic-winston-logger": "^2.
|
|
33
|
-
"@mimik/swagger-helper": "^5.0.
|
|
31
|
+
"@mimik/request-retry": "^4.0.11",
|
|
32
|
+
"@mimik/response-helper": "^4.0.11",
|
|
33
|
+
"@mimik/sumologic-winston-logger": "^2.2.2",
|
|
34
|
+
"@mimik/swagger-helper": "^5.0.4",
|
|
34
35
|
"ajv-formats": "3.0.1",
|
|
35
36
|
"js-base64": "3.7.8",
|
|
36
37
|
"js-yaml": "4.1.1",
|
|
37
38
|
"jsonwebtoken": "9.0.3",
|
|
38
39
|
"openapi-backend": "5.16.1",
|
|
39
|
-
"swagger-client": "3.37.
|
|
40
|
+
"swagger-client": "3.37.1"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"@eslint/js": "
|
|
43
|
-
"@mimik/eslint-plugin-document-env": "^2.0.
|
|
44
|
-
"@
|
|
43
|
+
"@eslint/js": "10.0.1",
|
|
44
|
+
"@mimik/eslint-plugin-document-env": "^2.0.9",
|
|
45
|
+
"@mimik/eslint-plugin-logger": "^1.0.3",
|
|
46
|
+
"@stylistic/eslint-plugin": "5.10.0",
|
|
45
47
|
"c8": "11.0.0",
|
|
46
48
|
"chai": "6.2.2",
|
|
47
|
-
"eslint": "
|
|
48
|
-
"eslint-plugin-import": "
|
|
49
|
+
"eslint": "10.1.0",
|
|
50
|
+
"eslint-plugin-import-x": "4.16.2",
|
|
49
51
|
"esmock": "2.7.3",
|
|
50
52
|
"globals": "17.4.0",
|
|
51
53
|
"husky": "9.1.7",
|