@itentialopensource/adapter-utils 4.44.9
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/.eslintignore +3 -0
- package/.eslintrc.js +18 -0
- package/.jshintrc +3 -0
- package/CHANGELOG.md +1398 -0
- package/CODE_OF_CONDUCT.md +48 -0
- package/CONTRIBUTING.md +173 -0
- package/LICENSE +201 -0
- package/README.md +12 -0
- package/actionSchema.json +186 -0
- package/error.json +148 -0
- package/index.js +7 -0
- package/lib/connectorRest.js +4083 -0
- package/lib/dbUtil.js +1300 -0
- package/lib/propertyUtil.js +1012 -0
- package/lib/requestHandler.js +1175 -0
- package/lib/restHandler.js +1309 -0
- package/lib/throttle.js +1289 -0
- package/lib/translatorUtil.js +1137 -0
- package/package.json +61 -0
- package/propertiesSchema.json +840 -0
- package/utils/pre-commit.sh +26 -0
- package/utils/setup.js +32 -0
- package/utils/testRunner.js +259 -0
|
@@ -0,0 +1,1012 @@
|
|
|
1
|
+
/* @copyright Itential, LLC 2018-9 */
|
|
2
|
+
|
|
3
|
+
// Set globals
|
|
4
|
+
/* global log */
|
|
5
|
+
|
|
6
|
+
/* NodeJS internal utilities */
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
// The crypto libraries
|
|
11
|
+
const cryptoJS = require('crypto-js');
|
|
12
|
+
|
|
13
|
+
class AdapterPropertyUtil {
|
|
14
|
+
/**
|
|
15
|
+
* Adapter Translator Utility
|
|
16
|
+
* @constructor
|
|
17
|
+
*/
|
|
18
|
+
constructor(prongId, directory) {
|
|
19
|
+
this.myid = prongId;
|
|
20
|
+
this.baseDir = directory;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// GENERIC UTILITY CALLS FOR PROPERTIES
|
|
24
|
+
/**
|
|
25
|
+
* @summary Get the entity schema and information for the action
|
|
26
|
+
*
|
|
27
|
+
* @function getEntitySchemaFromFS
|
|
28
|
+
* @param {String} entityName - the name of the entity (required)
|
|
29
|
+
* @param {String} actionName - the name of the action to take (required)
|
|
30
|
+
*
|
|
31
|
+
* @return {Object} entitySchema - the entity schema object
|
|
32
|
+
*/
|
|
33
|
+
getEntitySchemaFromFS(entityName, actionName) {
|
|
34
|
+
const origin = `${this.myid}-propertyUtil-getEntitySchemaFromFS`;
|
|
35
|
+
log.trace(origin);
|
|
36
|
+
|
|
37
|
+
// create the generic part of an error object
|
|
38
|
+
const errorObj = {
|
|
39
|
+
origin
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
// verify required data
|
|
44
|
+
if (!entityName || typeof entityName !== 'string') {
|
|
45
|
+
// add the specific pieces of the error object
|
|
46
|
+
errorObj.type = 'Missing Data';
|
|
47
|
+
errorObj.vars = ['Entity'];
|
|
48
|
+
log.error(`${origin}: Entity is required to get entity schema for action`);
|
|
49
|
+
throw new Error(JSON.stringify(errorObj));
|
|
50
|
+
}
|
|
51
|
+
if (!actionName || typeof actionName !== 'string') {
|
|
52
|
+
// add the specific pieces of the error object
|
|
53
|
+
errorObj.type = 'Missing Data';
|
|
54
|
+
errorObj.vars = ['Action'];
|
|
55
|
+
|
|
56
|
+
// log (if not system entity) and throw the error
|
|
57
|
+
if (entityName !== '.system') {
|
|
58
|
+
log.error(`${origin}: Action is required to get entity schema for action`);
|
|
59
|
+
}
|
|
60
|
+
throw new Error(JSON.stringify(errorObj));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// get the path for the specific action file
|
|
64
|
+
const actionFile = path.join(this.baseDir, `/entities/${entityName}/action.json`);
|
|
65
|
+
|
|
66
|
+
// if the file does not exist - error
|
|
67
|
+
if (!fs.existsSync(actionFile)) {
|
|
68
|
+
// add the specific pieces of the error object
|
|
69
|
+
errorObj.type = 'Missing File';
|
|
70
|
+
errorObj.vars = [actionFile];
|
|
71
|
+
|
|
72
|
+
// log (if not system entity) and throw the error
|
|
73
|
+
if (entityName !== '.system') {
|
|
74
|
+
log.error(`${origin}: Could not find file - ${actionFile}`);
|
|
75
|
+
}
|
|
76
|
+
throw new Error(JSON.stringify(errorObj));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Read the action from the file system
|
|
80
|
+
const entityActions = JSON.parse(fs.readFileSync(actionFile, 'utf-8'));
|
|
81
|
+
|
|
82
|
+
// handle possible errors in the action file
|
|
83
|
+
if (!entityActions || typeof entityActions !== 'object') {
|
|
84
|
+
// add the specific pieces of the error object
|
|
85
|
+
errorObj.type = 'Invalid Action File';
|
|
86
|
+
errorObj.vars = ['invalid format', actionFile];
|
|
87
|
+
|
|
88
|
+
// log (if not system entity) and throw the error
|
|
89
|
+
if (entityName !== '.system') {
|
|
90
|
+
log.error(`${origin}: Invalid entity action file, please verify file: ${actionFile}`);
|
|
91
|
+
}
|
|
92
|
+
throw new Error(JSON.stringify(errorObj));
|
|
93
|
+
}
|
|
94
|
+
if (!entityActions.actions || !Array.isArray(entityActions.actions)) {
|
|
95
|
+
// add the specific pieces of the error object
|
|
96
|
+
errorObj.type = 'Invalid Action File';
|
|
97
|
+
errorObj.vars = ['missing array of actions', actionFile];
|
|
98
|
+
|
|
99
|
+
// log (if not system entity) and throw the error
|
|
100
|
+
if (entityName !== '.system') {
|
|
101
|
+
log.error(`${origin}: Invalid action file syntax ${actionFile} - must contain an array of actions`);
|
|
102
|
+
}
|
|
103
|
+
throw new Error(JSON.stringify(errorObj));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let actionInfo = null;
|
|
107
|
+
|
|
108
|
+
// get the specific action information
|
|
109
|
+
for (let i = 0; i < entityActions.actions.length; i += 1) {
|
|
110
|
+
if (entityActions.actions[i].name === actionName) {
|
|
111
|
+
actionInfo = entityActions.actions[i];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// if there are no actions - invalid
|
|
116
|
+
if (actionInfo === null) {
|
|
117
|
+
// add the specific pieces of the error object
|
|
118
|
+
errorObj.type = 'Invalid Action File';
|
|
119
|
+
errorObj.vars = ['missing action', actionFile];
|
|
120
|
+
|
|
121
|
+
// log (if not system entity) and throw the error
|
|
122
|
+
if (entityName !== '.system') {
|
|
123
|
+
log.error(`${origin}: Entity ${entityName} - action file missing action: ${actionName}`);
|
|
124
|
+
}
|
|
125
|
+
throw new Error(JSON.stringify(errorObj));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// verify required action info - protocol, method, entitypath and schema
|
|
129
|
+
if (!actionInfo.protocol) {
|
|
130
|
+
// add the specific pieces of the error object
|
|
131
|
+
errorObj.type = 'Invalid Action File';
|
|
132
|
+
errorObj.vars = ['missing protocol', actionFile];
|
|
133
|
+
|
|
134
|
+
// log (if not system entity) and throw the error
|
|
135
|
+
if (entityName !== '.system') {
|
|
136
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing protocol`);
|
|
137
|
+
}
|
|
138
|
+
throw new Error(JSON.stringify(errorObj));
|
|
139
|
+
}
|
|
140
|
+
if (!actionInfo.method) {
|
|
141
|
+
// add the specific pieces of the error object
|
|
142
|
+
errorObj.type = 'Invalid Action File';
|
|
143
|
+
errorObj.vars = ['missing method', actionFile];
|
|
144
|
+
|
|
145
|
+
// log (if not system entity) and throw the error
|
|
146
|
+
if (entityName !== '.system') {
|
|
147
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing method`);
|
|
148
|
+
}
|
|
149
|
+
throw new Error(JSON.stringify(errorObj));
|
|
150
|
+
}
|
|
151
|
+
if (!actionInfo.entitypath) {
|
|
152
|
+
// add the specific pieces of the error object
|
|
153
|
+
errorObj.type = 'Invalid Action File';
|
|
154
|
+
errorObj.vars = ['missing entity path', actionFile];
|
|
155
|
+
|
|
156
|
+
// log (if not system entity) and throw the error
|
|
157
|
+
if (entityName !== '.system') {
|
|
158
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
|
|
159
|
+
}
|
|
160
|
+
throw new Error(JSON.stringify(errorObj));
|
|
161
|
+
}
|
|
162
|
+
if (!actionInfo.schema && (!actionInfo.requestSchema || !actionInfo.responseSchema)) {
|
|
163
|
+
// add the specific pieces of the error object
|
|
164
|
+
errorObj.type = 'Invalid Action File';
|
|
165
|
+
errorObj.vars = ['missing schema', actionFile];
|
|
166
|
+
|
|
167
|
+
// log (if not system entity) and throw the error
|
|
168
|
+
if (entityName !== '.system') {
|
|
169
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing schema`);
|
|
170
|
+
}
|
|
171
|
+
throw new Error(JSON.stringify(errorObj));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// get the schema file name
|
|
175
|
+
let reqSchemaName = actionInfo.schema;
|
|
176
|
+
let respSchemaName = actionInfo.schema;
|
|
177
|
+
|
|
178
|
+
// if there is a separate request schema file it overrides the default schema
|
|
179
|
+
if (actionInfo.requestSchema) {
|
|
180
|
+
reqSchemaName = actionInfo.requestSchema;
|
|
181
|
+
}
|
|
182
|
+
// if there is a separate response schema file it overrides the default schema
|
|
183
|
+
if (actionInfo.responseSchema) {
|
|
184
|
+
respSchemaName = actionInfo.responseSchema;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// get the path for the specific schema file
|
|
188
|
+
const reqSchemaFile = path.join(this.baseDir, `/entities/${entityName}/${reqSchemaName}`);
|
|
189
|
+
const respSchemaFile = path.join(this.baseDir, `/entities/${entityName}/${respSchemaName}`);
|
|
190
|
+
|
|
191
|
+
// if the file does not exist - error
|
|
192
|
+
if (!fs.existsSync(reqSchemaFile)) {
|
|
193
|
+
// add the specific pieces of the error object
|
|
194
|
+
errorObj.type = 'Missing File';
|
|
195
|
+
errorObj.vars = [reqSchemaFile];
|
|
196
|
+
|
|
197
|
+
// log (if not system entity) and throw the error
|
|
198
|
+
if (entityName !== '.system') {
|
|
199
|
+
log.error(`${origin}: Could not find file - ${reqSchemaFile}`);
|
|
200
|
+
}
|
|
201
|
+
throw new Error(JSON.stringify(errorObj));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// if the file does not exist - error
|
|
205
|
+
if (!fs.existsSync(respSchemaFile)) {
|
|
206
|
+
// add the specific pieces of the error object
|
|
207
|
+
errorObj.type = 'Missing File';
|
|
208
|
+
errorObj.vars = [respSchemaFile];
|
|
209
|
+
|
|
210
|
+
// log (if not system entity) and throw the error
|
|
211
|
+
if (entityName !== '.system') {
|
|
212
|
+
log.error(`${origin}: Could not find file - ${respSchemaFile}`);
|
|
213
|
+
}
|
|
214
|
+
throw new Error(JSON.stringify(errorObj));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Read the entity schema from the file system
|
|
218
|
+
const entitySchema = {
|
|
219
|
+
requestSchema: JSON.parse(fs.readFileSync(reqSchemaFile, 'utf-8')),
|
|
220
|
+
responseSchema: JSON.parse(fs.readFileSync(respSchemaFile, 'utf-8'))
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// handle possible errors on the schema
|
|
224
|
+
if (!entitySchema.requestSchema || typeof entitySchema.requestSchema !== 'object') {
|
|
225
|
+
// add the specific pieces of the error object
|
|
226
|
+
errorObj.type = 'Invalid Schema File';
|
|
227
|
+
errorObj.vars = ['invalid format', reqSchemaFile];
|
|
228
|
+
|
|
229
|
+
// log (if not system entity) and throw the error
|
|
230
|
+
if (entityName !== '.system') {
|
|
231
|
+
log.error(`${origin}: Invalid entity request schema, please verify file: ${reqSchemaFile}`);
|
|
232
|
+
}
|
|
233
|
+
throw new Error(JSON.stringify(errorObj));
|
|
234
|
+
}
|
|
235
|
+
if (!entitySchema.responseSchema || typeof entitySchema.responseSchema !== 'object') {
|
|
236
|
+
// add the specific pieces of the error object
|
|
237
|
+
errorObj.type = 'Invalid Schema File';
|
|
238
|
+
errorObj.vars = ['invalid format', respSchemaFile];
|
|
239
|
+
|
|
240
|
+
// log (if not system entity) and throw the error
|
|
241
|
+
if (entityName !== '.system') {
|
|
242
|
+
log.error(`${origin}: Invalid entity response schema, please verify file: ${respSchemaFile}`);
|
|
243
|
+
}
|
|
244
|
+
throw new Error(JSON.stringify(errorObj));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Merge the information into the entity schema
|
|
248
|
+
entitySchema.protocol = actionInfo.protocol;
|
|
249
|
+
entitySchema.method = actionInfo.method;
|
|
250
|
+
entitySchema.timeout = actionInfo.timeout;
|
|
251
|
+
entitySchema.entitypath = actionInfo.entitypath;
|
|
252
|
+
entitySchema.querykey = '?';
|
|
253
|
+
entitySchema.responseObjects = [];
|
|
254
|
+
entitySchema.mockresponses = [];
|
|
255
|
+
|
|
256
|
+
// if info provided, replace the defaults
|
|
257
|
+
if (actionInfo.querykey) {
|
|
258
|
+
entitySchema.querykey = actionInfo.querykey;
|
|
259
|
+
}
|
|
260
|
+
if (actionInfo.responseObjects) {
|
|
261
|
+
entitySchema.responseObjects = actionInfo.responseObjects;
|
|
262
|
+
}
|
|
263
|
+
if (actionInfo.headers) {
|
|
264
|
+
entitySchema.headers = actionInfo.headers;
|
|
265
|
+
}
|
|
266
|
+
if (actionInfo.requestDatatype) {
|
|
267
|
+
entitySchema.requestDatatype = actionInfo.requestDatatype;
|
|
268
|
+
} else if (actionInfo.datatype) {
|
|
269
|
+
entitySchema.requestDatatype = actionInfo.datatype;
|
|
270
|
+
} else {
|
|
271
|
+
entitySchema.requestDatatype = 'JSON';
|
|
272
|
+
}
|
|
273
|
+
if (actionInfo.responseDatatype) {
|
|
274
|
+
entitySchema.responseDatatype = actionInfo.responseDatatype;
|
|
275
|
+
} else if (actionInfo.datatype) {
|
|
276
|
+
entitySchema.responseDatatype = actionInfo.datatype;
|
|
277
|
+
} else {
|
|
278
|
+
entitySchema.responseDatatype = 'JSON';
|
|
279
|
+
}
|
|
280
|
+
if (Object.hasOwnProperty.call(actionInfo, 'sendEmpty')) {
|
|
281
|
+
entitySchema.sendEmpty = actionInfo.sendEmpty;
|
|
282
|
+
}
|
|
283
|
+
if (Object.hasOwnProperty.call(actionInfo, 'sendGetBody')) {
|
|
284
|
+
entitySchema.sendGetBody = actionInfo.sendGetBody;
|
|
285
|
+
}
|
|
286
|
+
if (actionInfo.sso) {
|
|
287
|
+
entitySchema.sso = actionInfo.sso;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// need to make sure we have supported datatypes - PLAIN is best if not supported - no translation or encoding
|
|
291
|
+
if (entitySchema.requestDatatype.toUpperCase() !== 'JSON' && entitySchema.requestDatatype.toUpperCase() !== 'XML'
|
|
292
|
+
&& entitySchema.requestDatatype.toUpperCase() !== 'URLENCODE' && entitySchema.requestDatatype.toUpperCase() !== 'FORM'
|
|
293
|
+
&& entitySchema.requestDatatype.toUpperCase() !== 'JSON2XML') {
|
|
294
|
+
entitySchema.requestDatatype = 'PLAIN';
|
|
295
|
+
}
|
|
296
|
+
if (entitySchema.responseDatatype.toUpperCase() !== 'JSON' && entitySchema.responseDatatype.toUpperCase() !== 'XML'
|
|
297
|
+
&& entitySchema.responseDatatype.toUpperCase() !== 'URLENCODE' && entitySchema.responseDatatype.toUpperCase() !== 'XML2JSON') {
|
|
298
|
+
entitySchema.responseDatatype = 'PLAIN';
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// go through each response object to see if there is mock data
|
|
302
|
+
for (let i = 0; i < entitySchema.responseObjects.length; i += 1) {
|
|
303
|
+
entitySchema.responseObjects[i].name = entitySchema.entitypath;
|
|
304
|
+
entitySchema.responseObjects[i].method = entitySchema.method;
|
|
305
|
+
|
|
306
|
+
// if there is mock data, read the mock data from the file system
|
|
307
|
+
if (entitySchema.responseObjects[i].mockFile) {
|
|
308
|
+
const mockResponse = {
|
|
309
|
+
name: entitySchema.responseObjects[i].name,
|
|
310
|
+
method: entitySchema.responseObjects[i].method,
|
|
311
|
+
type: entitySchema.responseObjects[i].type,
|
|
312
|
+
file: entitySchema.responseObjects[i].mockFile
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
// get the mock file name
|
|
316
|
+
const tempName = entitySchema.responseObjects[i].mockFile;
|
|
317
|
+
|
|
318
|
+
// if the file name was provided
|
|
319
|
+
if (tempName) {
|
|
320
|
+
const mockFileName = path.join(this.baseDir, `/entities/${entityName}/${tempName}`);
|
|
321
|
+
|
|
322
|
+
// if the file does not exist - throw warning
|
|
323
|
+
if (fs.existsSync(mockFileName)) {
|
|
324
|
+
// set the normal headers based on the type of data for the call
|
|
325
|
+
if (entitySchema.responseDatatype && entitySchema.responseDatatype.toUpperCase() === 'PLAIN') {
|
|
326
|
+
// read the mock date from the file system
|
|
327
|
+
mockResponse.response = fs.readFileSync(mockFileName, 'utf-8');
|
|
328
|
+
} else if (entitySchema.responseDatatype && (entitySchema.responseDatatype.toUpperCase() === 'XML'
|
|
329
|
+
|| entitySchema.responseDatatype.toUpperCase() === 'XML2JSON')) {
|
|
330
|
+
// read the mock date from the file system
|
|
331
|
+
mockResponse.response = fs.readFileSync(mockFileName, 'utf-8');
|
|
332
|
+
} else {
|
|
333
|
+
// read the mock date from the file system
|
|
334
|
+
try {
|
|
335
|
+
// parse the mockdata file to store it as an object
|
|
336
|
+
mockResponse.response = JSON.parse(fs.readFileSync(mockFileName, 'utf-8'));
|
|
337
|
+
} catch (excep) {
|
|
338
|
+
log.warn(`${origin}: Could not parse file - ${mockFileName}`);
|
|
339
|
+
mockResponse.response = '';
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
} else {
|
|
343
|
+
log.warn(`${origin}: Could not find file - ${mockFileName}`);
|
|
344
|
+
mockResponse.response = null;
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
mockResponse.response = null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// add the response to the array of mock responses
|
|
351
|
+
entitySchema.mockresponses.push(mockResponse);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// return the entity schema
|
|
356
|
+
return entitySchema;
|
|
357
|
+
} catch (e) {
|
|
358
|
+
let internal = null;
|
|
359
|
+
errorObj.type = 'Caught Exception';
|
|
360
|
+
errorObj.vars = [];
|
|
361
|
+
errorObj.exception = e;
|
|
362
|
+
|
|
363
|
+
// determine if we already had an internal message
|
|
364
|
+
try {
|
|
365
|
+
internal = JSON.parse(e.message);
|
|
366
|
+
} catch (ex) {
|
|
367
|
+
// message was not internal
|
|
368
|
+
log.error(`${origin}: Issue parsing entity schema: ${e}`);
|
|
369
|
+
internal = null;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// return the appropriate error message
|
|
373
|
+
if (internal && internal.origin && internal.type) {
|
|
374
|
+
throw e;
|
|
375
|
+
} else {
|
|
376
|
+
throw new Error(JSON.stringify(errorObj));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @summary Build the entitySchema structure from DB config
|
|
383
|
+
*
|
|
384
|
+
* @function getEntitySchemaFromDB
|
|
385
|
+
* @param {Object} dbObj - the database connect information (optional)
|
|
386
|
+
* @param {String} entityName - the name of the entity (required)
|
|
387
|
+
* @param {String} actionName - the name of the action to take (required)
|
|
388
|
+
*
|
|
389
|
+
* @return {Object} entitySchema - the entity schema object
|
|
390
|
+
*/
|
|
391
|
+
getEntitySchemaFromDB(dbObj, entityName, actionName, dbUtils, callback) {
|
|
392
|
+
const origin = `${this.myid}-propertyUtil-getEntitySchemaFromDB`;
|
|
393
|
+
log.trace(origin);
|
|
394
|
+
|
|
395
|
+
// create the generic part of an error object
|
|
396
|
+
const errorObj = {
|
|
397
|
+
origin,
|
|
398
|
+
isError: true
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
try {
|
|
402
|
+
// verify required data
|
|
403
|
+
if (!entityName || typeof entityName !== 'string') {
|
|
404
|
+
// add the specific pieces of the error object
|
|
405
|
+
errorObj.type = 'Missing Data';
|
|
406
|
+
errorObj.vars = ['Entity'];
|
|
407
|
+
log.error(`${origin}: Entity is required to get entity schema for action`);
|
|
408
|
+
errorObj.error = [`${origin}: Entity is required to get entity schema for action`];
|
|
409
|
+
return callback(null, errorObj);
|
|
410
|
+
}
|
|
411
|
+
if (!actionName || typeof actionName !== 'string') {
|
|
412
|
+
// add the specific pieces of the error object
|
|
413
|
+
errorObj.type = 'Missing Data';
|
|
414
|
+
errorObj.vars = ['Action'];
|
|
415
|
+
|
|
416
|
+
// log (if not system entity) and return the error
|
|
417
|
+
if (entityName !== '.system') {
|
|
418
|
+
log.error(`${origin}: Action is required to get entity schema for action`);
|
|
419
|
+
errorObj.error = [`${origin}: Action is required to get entity schema for action`];
|
|
420
|
+
}
|
|
421
|
+
return callback(null, errorObj);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
let entitySchema = null;
|
|
425
|
+
|
|
426
|
+
// set up the options-filter
|
|
427
|
+
const dbOpts = {
|
|
428
|
+
filter: {
|
|
429
|
+
id: this.myid,
|
|
430
|
+
entity: entityName
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// call to get the adapter schema from the database
|
|
435
|
+
return dbUtils.find('adapter_configs', dbOpts, dbObj, null, (dbError, dbResult) => {
|
|
436
|
+
if (dbError) {
|
|
437
|
+
// add the specific pieces of the error object
|
|
438
|
+
errorObj.type = 'Database Error';
|
|
439
|
+
errorObj.vars = ['dbError'];
|
|
440
|
+
log.error(`${origin}: Database Error: ${dbError}`);
|
|
441
|
+
errorObj.error = [`${origin}: Database Error: ${dbError}`];
|
|
442
|
+
return callback(null, errorObj);
|
|
443
|
+
}
|
|
444
|
+
if (!dbResult) {
|
|
445
|
+
// add the specific pieces of the error object
|
|
446
|
+
errorObj.type = 'Missing Data';
|
|
447
|
+
errorObj.vars = ['Entity'];
|
|
448
|
+
log.error(`${origin}: Entity was not found in the database`);
|
|
449
|
+
errorObj.error = [`${origin}: Entity was not found in the database`];
|
|
450
|
+
return callback(null, errorObj);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Read the action from the entity object
|
|
454
|
+
const entityActions = dbResult[0];
|
|
455
|
+
|
|
456
|
+
// handle possible errors in the action file
|
|
457
|
+
if (!entityActions || typeof entityActions !== 'object') {
|
|
458
|
+
// add the specific pieces of the error object
|
|
459
|
+
errorObj.type = 'Invalid Action File';
|
|
460
|
+
errorObj.vars = ['invalid format', entityName];
|
|
461
|
+
|
|
462
|
+
// log (if not system entity) and return the error
|
|
463
|
+
if (entityName !== '.system') {
|
|
464
|
+
log.error(`${origin}: Invalid entity action file, please verify file: ${entityName}`);
|
|
465
|
+
errorObj.error = [`${origin}: Invalid entity action file, please verify file: ${entityName}`];
|
|
466
|
+
}
|
|
467
|
+
return callback(null, errorObj);
|
|
468
|
+
}
|
|
469
|
+
if (!entityActions.actions || !Array.isArray(entityActions.actions)) {
|
|
470
|
+
// add the specific pieces of the error object
|
|
471
|
+
errorObj.type = 'Invalid Action File';
|
|
472
|
+
errorObj.vars = ['missing array of actions', entityName];
|
|
473
|
+
|
|
474
|
+
// log (if not system entity) and return the error
|
|
475
|
+
if (entityName !== '.system') {
|
|
476
|
+
log.error(`${origin}: Invalid action file syntax ${entityName} - must contain an array of actions`);
|
|
477
|
+
errorObj.error = [`${origin}: Invalid action file syntax ${entityName} - must contain an array of actions`];
|
|
478
|
+
}
|
|
479
|
+
return callback(null, errorObj);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
let actionInfo = null;
|
|
483
|
+
|
|
484
|
+
// get the specific action information
|
|
485
|
+
for (let i = 0; i < entityActions.actions.length; i += 1) {
|
|
486
|
+
if (entityActions.actions[i].name === actionName) {
|
|
487
|
+
actionInfo = entityActions.actions[i];
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// if there are no actions - invalid
|
|
492
|
+
if (actionInfo === null) {
|
|
493
|
+
// add the specific pieces of the error object
|
|
494
|
+
errorObj.type = 'Invalid Action File';
|
|
495
|
+
errorObj.vars = ['missing action', entityName];
|
|
496
|
+
|
|
497
|
+
// log (if not system entity) and return the error
|
|
498
|
+
if (entityName !== '.system') {
|
|
499
|
+
log.error(`${origin}: Entity ${entityName} - action file missing action: ${actionName}`);
|
|
500
|
+
errorObj.error = [`${origin}: Entity ${entityName} - action file missing action: ${actionName}`];
|
|
501
|
+
}
|
|
502
|
+
return callback(null, errorObj);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// verify required action info - protocol, method, entitypath and schema
|
|
506
|
+
if (!actionInfo.protocol) {
|
|
507
|
+
// add the specific pieces of the error object
|
|
508
|
+
errorObj.type = 'Invalid Action File';
|
|
509
|
+
errorObj.vars = ['missing protocol', entityName];
|
|
510
|
+
|
|
511
|
+
// log (if not system entity) and return the error
|
|
512
|
+
if (entityName !== '.system') {
|
|
513
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing protocol`);
|
|
514
|
+
errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing protocol`];
|
|
515
|
+
}
|
|
516
|
+
return callback(null, errorObj);
|
|
517
|
+
}
|
|
518
|
+
if (!actionInfo.method) {
|
|
519
|
+
// add the specific pieces of the error object
|
|
520
|
+
errorObj.type = 'Invalid Action File';
|
|
521
|
+
errorObj.vars = ['missing method', entityName];
|
|
522
|
+
|
|
523
|
+
// log (if not system entity) and return the error
|
|
524
|
+
if (entityName !== '.system') {
|
|
525
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing method`);
|
|
526
|
+
errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing method`];
|
|
527
|
+
}
|
|
528
|
+
return callback(null, errorObj);
|
|
529
|
+
}
|
|
530
|
+
if (!actionInfo.entitypath) {
|
|
531
|
+
// add the specific pieces of the error object
|
|
532
|
+
errorObj.type = 'Invalid Action File';
|
|
533
|
+
errorObj.vars = ['missing entity path', entityName];
|
|
534
|
+
|
|
535
|
+
// log (if not system entity) and return the error
|
|
536
|
+
if (entityName !== '.system') {
|
|
537
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing entity path`);
|
|
538
|
+
errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing entity path`];
|
|
539
|
+
}
|
|
540
|
+
return callback(null, errorObj);
|
|
541
|
+
}
|
|
542
|
+
if (!actionInfo.schema && (!actionInfo.requestSchema || !actionInfo.responseSchema)) {
|
|
543
|
+
// add the specific pieces of the error object
|
|
544
|
+
errorObj.type = 'Invalid Action File';
|
|
545
|
+
errorObj.vars = ['missing schema', entityName];
|
|
546
|
+
|
|
547
|
+
// log (if not system entity) and return the error
|
|
548
|
+
if (entityName !== '.system') {
|
|
549
|
+
log.error(`${origin}: Entity ${entityName} action ${actionName} - missing schema`);
|
|
550
|
+
errorObj.error = [`${origin}: Entity ${entityName} action ${actionName} - missing schema`];
|
|
551
|
+
}
|
|
552
|
+
return callback(null, errorObj);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// get the schema file name
|
|
556
|
+
let reqSchemaName = actionInfo.schema;
|
|
557
|
+
let respSchemaName = actionInfo.schema;
|
|
558
|
+
|
|
559
|
+
// if there is a separate request schema file it overrides the default schema
|
|
560
|
+
if (actionInfo.requestSchema) {
|
|
561
|
+
reqSchemaName = actionInfo.requestSchema;
|
|
562
|
+
}
|
|
563
|
+
// if there is a separate response schema file it overrides the default schema
|
|
564
|
+
if (actionInfo.responseSchema) {
|
|
565
|
+
respSchemaName = actionInfo.responseSchema;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
if (!entityActions.schema || !Array.isArray(entityActions.schema)) {
|
|
569
|
+
// add the specific pieces of the error object
|
|
570
|
+
errorObj.type = 'Invalid Schema File';
|
|
571
|
+
errorObj.vars = ['missing array of schemas', reqSchemaName];
|
|
572
|
+
|
|
573
|
+
// log (if not system entity) and return the error
|
|
574
|
+
if (entityName !== '.system') {
|
|
575
|
+
log.error(`${origin}: Invalid schema file syntax ${reqSchemaName} - must contain an array of schemas`);
|
|
576
|
+
errorObj.error = [`${origin}: Invalid schema file syntax ${reqSchemaName} - must contain an array of schemas`];
|
|
577
|
+
}
|
|
578
|
+
return callback(null, errorObj);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
let reqSchemaInfo = null;
|
|
582
|
+
let respSchemaInfo = null;
|
|
583
|
+
|
|
584
|
+
// get the specific action information
|
|
585
|
+
for (let i = 0; i < entityActions.schema.length; i += 1) {
|
|
586
|
+
if (entityActions.schema[i].name === reqSchemaName) {
|
|
587
|
+
reqSchemaInfo = entityActions.schema[i].schema;
|
|
588
|
+
}
|
|
589
|
+
if (entityActions.schema[i].name === respSchemaName) {
|
|
590
|
+
respSchemaInfo = entityActions.schema[i].schema;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// if there are no actions - invalid
|
|
595
|
+
if (reqSchemaInfo === null) {
|
|
596
|
+
// add the specific pieces of the error object
|
|
597
|
+
errorObj.type = 'Missing File';
|
|
598
|
+
errorObj.vars = [reqSchemaName];
|
|
599
|
+
|
|
600
|
+
// log (if not system entity) and return the error
|
|
601
|
+
if (entityName !== '.system') {
|
|
602
|
+
log.error(`${origin}: Could not find file - ${reqSchemaName}`);
|
|
603
|
+
errorObj.error = [`${origin}: Could not find file - ${reqSchemaName}`];
|
|
604
|
+
}
|
|
605
|
+
return callback(null, errorObj);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// if there are no actions - invalid
|
|
609
|
+
if (respSchemaInfo === null) {
|
|
610
|
+
// add the specific pieces of the error object
|
|
611
|
+
errorObj.type = 'Missing File';
|
|
612
|
+
errorObj.vars = [respSchemaName];
|
|
613
|
+
|
|
614
|
+
// log (if not system entity) and return the error
|
|
615
|
+
if (entityName !== '.system') {
|
|
616
|
+
log.error(`${origin}: Could not find file - ${respSchemaName}`);
|
|
617
|
+
errorObj.error = [`${origin}: Could not find file - ${respSchemaName}`];
|
|
618
|
+
}
|
|
619
|
+
return callback(null, errorObj);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// handle possible errors on the schema
|
|
623
|
+
if (typeof reqSchemaInfo !== 'object') {
|
|
624
|
+
// add the specific pieces of the error object
|
|
625
|
+
errorObj.type = 'Invalid Schema File';
|
|
626
|
+
errorObj.vars = ['invalid format', reqSchemaInfo];
|
|
627
|
+
|
|
628
|
+
// log (if not system entity) and return the error
|
|
629
|
+
if (entityName !== '.system') {
|
|
630
|
+
log.error(`${origin}: Invalid entity request schema, please verify file: ${reqSchemaInfo}`);
|
|
631
|
+
errorObj.error = [`${origin}: Invalid entity request schema, please verify file: ${reqSchemaInfo}`];
|
|
632
|
+
}
|
|
633
|
+
return callback(null, errorObj);
|
|
634
|
+
}
|
|
635
|
+
if (typeof respSchemaInfo !== 'object') {
|
|
636
|
+
// add the specific pieces of the error object
|
|
637
|
+
errorObj.type = 'Invalid Schema File';
|
|
638
|
+
errorObj.vars = ['invalid format', respSchemaInfo];
|
|
639
|
+
|
|
640
|
+
// log (if not system entity) and return the error
|
|
641
|
+
if (entityName !== '.system') {
|
|
642
|
+
log.error(`${origin}: Invalid entity response schema, please verify file: ${respSchemaInfo}`);
|
|
643
|
+
errorObj.error = [`${origin}: Invalid entity response schema, please verify file: ${respSchemaInfo}`];
|
|
644
|
+
}
|
|
645
|
+
return callback(null, errorObj);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Read the entity schema from the file system
|
|
649
|
+
entitySchema = {
|
|
650
|
+
requestSchema: reqSchemaInfo,
|
|
651
|
+
responseSchema: respSchemaInfo
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
// Merge the information into the entity schema
|
|
655
|
+
entitySchema.protocol = actionInfo.protocol;
|
|
656
|
+
entitySchema.method = actionInfo.method;
|
|
657
|
+
entitySchema.timeout = actionInfo.timeout;
|
|
658
|
+
entitySchema.entitypath = actionInfo.entitypath;
|
|
659
|
+
entitySchema.querykey = '?';
|
|
660
|
+
entitySchema.responseObjects = [];
|
|
661
|
+
entitySchema.mockresponses = [];
|
|
662
|
+
|
|
663
|
+
// if info provided, replace the defaults
|
|
664
|
+
if (actionInfo.querykey) {
|
|
665
|
+
entitySchema.querykey = actionInfo.querykey;
|
|
666
|
+
}
|
|
667
|
+
if (actionInfo.responseObjects) {
|
|
668
|
+
entitySchema.responseObjects = actionInfo.responseObjects;
|
|
669
|
+
}
|
|
670
|
+
if (actionInfo.headers) {
|
|
671
|
+
entitySchema.headers = actionInfo.headers;
|
|
672
|
+
}
|
|
673
|
+
if (actionInfo.requestDatatype) {
|
|
674
|
+
entitySchema.requestDatatype = actionInfo.requestDatatype;
|
|
675
|
+
} else if (actionInfo.datatype) {
|
|
676
|
+
entitySchema.requestDatatype = actionInfo.datatype;
|
|
677
|
+
} else {
|
|
678
|
+
entitySchema.requestDatatype = 'JSON';
|
|
679
|
+
}
|
|
680
|
+
if (actionInfo.responseDatatype) {
|
|
681
|
+
entitySchema.responseDatatype = actionInfo.responseDatatype;
|
|
682
|
+
} else if (actionInfo.datatype) {
|
|
683
|
+
entitySchema.responseDatatype = actionInfo.datatype;
|
|
684
|
+
} else {
|
|
685
|
+
entitySchema.responseDatatype = 'JSON';
|
|
686
|
+
}
|
|
687
|
+
if (Object.hasOwnProperty.call(actionInfo, 'sendEmpty')) {
|
|
688
|
+
entitySchema.sendEmpty = actionInfo.sendEmpty;
|
|
689
|
+
}
|
|
690
|
+
if (Object.hasOwnProperty.call(actionInfo, 'sendGetBody')) {
|
|
691
|
+
entitySchema.sendGetBody = actionInfo.sendGetBody;
|
|
692
|
+
}
|
|
693
|
+
if (actionInfo.sso) {
|
|
694
|
+
entitySchema.sso = actionInfo.sso;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// need to make sure we have supported datatypes - PLAIN is best if not supported - no translation or encoding
|
|
698
|
+
if (entitySchema.requestDatatype.toUpperCase() !== 'JSON' && entitySchema.requestDatatype.toUpperCase() !== 'XML'
|
|
699
|
+
&& entitySchema.requestDatatype.toUpperCase() !== 'URLENCODE' && entitySchema.requestDatatype.toUpperCase() !== 'FORM'
|
|
700
|
+
&& entitySchema.requestDatatype.toUpperCase() !== 'JSON2XML') {
|
|
701
|
+
entitySchema.requestDatatype = 'PLAIN';
|
|
702
|
+
}
|
|
703
|
+
if (entitySchema.responseDatatype.toUpperCase() !== 'JSON' && entitySchema.responseDatatype.toUpperCase() !== 'XML'
|
|
704
|
+
&& entitySchema.responseDatatype.toUpperCase() !== 'URLENCODE' && entitySchema.responseDatatype.toUpperCase() !== 'XML2JSON') {
|
|
705
|
+
entitySchema.responseDatatype = 'PLAIN';
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// go through each response object to see if there is mock data
|
|
709
|
+
for (let i = 0; i < entitySchema.responseObjects.length; i += 1) {
|
|
710
|
+
entitySchema.responseObjects[i].name = entitySchema.entitypath;
|
|
711
|
+
entitySchema.responseObjects[i].method = entitySchema.method;
|
|
712
|
+
|
|
713
|
+
// if there is mock data, read the mock data from the file system
|
|
714
|
+
if (entitySchema.responseObjects[i].mockFile) {
|
|
715
|
+
const mockResponse = {
|
|
716
|
+
name: entitySchema.responseObjects[i].name,
|
|
717
|
+
method: entitySchema.responseObjects[i].method,
|
|
718
|
+
type: entitySchema.responseObjects[i].type,
|
|
719
|
+
file: entitySchema.responseObjects[i].mockFile
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
// get the mock file name
|
|
723
|
+
const tempName = entitySchema.responseObjects[i].mockFile;
|
|
724
|
+
|
|
725
|
+
// if the file name was provided
|
|
726
|
+
if (tempName) {
|
|
727
|
+
// need to get just the file name
|
|
728
|
+
const mockFileArray = tempName.split('/');
|
|
729
|
+
const mockFileName = mockFileArray[mockFileArray.length - 1];
|
|
730
|
+
const mockResp = entityActions.mockdatafiles[mockFileName];
|
|
731
|
+
|
|
732
|
+
if (mockResp) {
|
|
733
|
+
// set the normal headers based on the type of data for the call
|
|
734
|
+
if (entitySchema.responseDatatype && entitySchema.responseDatatype.toUpperCase() === 'PLAIN') {
|
|
735
|
+
// read the mock date from the file system
|
|
736
|
+
mockResponse.response = mockResp;
|
|
737
|
+
} else if (entitySchema.responseDatatype && (entitySchema.responseDatatype.toUpperCase() === 'XML'
|
|
738
|
+
|| entitySchema.responseDatatype.toUpperCase() === 'XML2JSON')) {
|
|
739
|
+
// read the mock date from the file system
|
|
740
|
+
mockResponse.response = mockResp;
|
|
741
|
+
} else {
|
|
742
|
+
// read the mock date from the file system
|
|
743
|
+
try {
|
|
744
|
+
// parse the mockdata file to store it as an object
|
|
745
|
+
mockResponse.response = mockResp;
|
|
746
|
+
} catch (excep) {
|
|
747
|
+
log.warn(`${origin}: Could not parse file - ${mockFileName}`);
|
|
748
|
+
mockResponse.response = '';
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
} else {
|
|
752
|
+
log.warn(`${origin}: Could not find file - ${mockFileName}`);
|
|
753
|
+
mockResponse.response = null;
|
|
754
|
+
}
|
|
755
|
+
} else {
|
|
756
|
+
mockResponse.response = null;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// add the response to the array of mock responses
|
|
760
|
+
entitySchema.mockresponses.push(mockResponse);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// return the entity schema
|
|
765
|
+
return callback(entitySchema, null);
|
|
766
|
+
});
|
|
767
|
+
} catch (e) {
|
|
768
|
+
errorObj.type = 'Caught Exception';
|
|
769
|
+
errorObj.vars = [];
|
|
770
|
+
errorObj.exception = e;
|
|
771
|
+
|
|
772
|
+
// return the error message
|
|
773
|
+
log.info(`unable to get adapter config from database: ${e}`);
|
|
774
|
+
return callback(null, errorObj);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* @summary Get the entity schema and information for the action
|
|
780
|
+
*
|
|
781
|
+
* @function getEntitySchema
|
|
782
|
+
* @param {String} entityName - the name of the entity (required)
|
|
783
|
+
* @param {String} actionName - the name of the action to take (required)
|
|
784
|
+
*
|
|
785
|
+
* @return {Object} entitySchema - the entity schema object
|
|
786
|
+
*/
|
|
787
|
+
getEntitySchema(entityName, actionName, dbUtils, callback) {
|
|
788
|
+
const origin = `${this.myid}-propertyUtil-getEntitySchema`;
|
|
789
|
+
log.trace(origin);
|
|
790
|
+
|
|
791
|
+
// need to try to get the entity schema from the adapter database
|
|
792
|
+
try {
|
|
793
|
+
// call to get the adapter schema from the database
|
|
794
|
+
return this.getEntitySchemaFromDB(null, entityName, actionName, dbUtils, (dbresp, dberror) => {
|
|
795
|
+
// if we got an error back - just means db config not in place
|
|
796
|
+
if (dberror || !dbresp || (dbresp && Object.keys(dbresp).length === 0)) {
|
|
797
|
+
log.debug('unable to get adapter config from adapter database');
|
|
798
|
+
|
|
799
|
+
// Temporarily hardcode the adapter properties
|
|
800
|
+
const iapDB = {
|
|
801
|
+
dburl: 'mongodb://127.0.0.1:27017',
|
|
802
|
+
dboptions: {},
|
|
803
|
+
database: 'pronghorn'
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
// need to try to get the entity schema from the iap database
|
|
807
|
+
return this.getEntitySchemaFromDB(iapDB, entityName, actionName, dbUtils, (iapdbresp, iapdberror) => {
|
|
808
|
+
// if we got an error back - just means db config not in place
|
|
809
|
+
if (iapdberror || !iapdbresp || (iapdbresp && Object.keys(iapdbresp).length === 0)) {
|
|
810
|
+
log.debug('unable to get adapter config from iap database');
|
|
811
|
+
|
|
812
|
+
// need to try to get the entity schema from the filesystem
|
|
813
|
+
log.debug('returning adapter config from file system');
|
|
814
|
+
try {
|
|
815
|
+
return callback(this.getEntitySchemaFromFS(entityName, actionName), null);
|
|
816
|
+
} catch (exc) {
|
|
817
|
+
log.error('Exception caught on File System');
|
|
818
|
+
return callback(null, exc);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// return the iap db config
|
|
823
|
+
log.debug(`returning adapter config from iap database ${iapdbresp}`);
|
|
824
|
+
return callback(iapdbresp, null);
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// return the adapter db config
|
|
829
|
+
log.debug(`returning adapter config from adapter database ${dbresp}`);
|
|
830
|
+
return callback(dbresp, null);
|
|
831
|
+
});
|
|
832
|
+
} catch (exaddb) {
|
|
833
|
+
log.debug(`unable to get adapter config: ${exaddb}`);
|
|
834
|
+
return callback(null, exaddb);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* @summary Takes in propertiesSchema and creates an object with all of the
|
|
840
|
+
* defaults set.
|
|
841
|
+
*
|
|
842
|
+
* @function setDefaults
|
|
843
|
+
* @param {Object} propSchema - the proeprty schema
|
|
844
|
+
*
|
|
845
|
+
* @return {Object} the object with default values from the property schema
|
|
846
|
+
*/
|
|
847
|
+
setDefaults(propSchema) {
|
|
848
|
+
const origin = `${this.myid}-propertyUtil-setDefaults`;
|
|
849
|
+
log.trace(origin);
|
|
850
|
+
|
|
851
|
+
const defaults = {};
|
|
852
|
+
|
|
853
|
+
// verify the input for the method
|
|
854
|
+
if (!propSchema || !propSchema.properties) {
|
|
855
|
+
return defaults;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
const propKeys = Object.keys(propSchema.properties);
|
|
859
|
+
|
|
860
|
+
// loop through all of the properties in the schema
|
|
861
|
+
for (let k = 0; k < propKeys.length; k += 1) {
|
|
862
|
+
const thisProp = propSchema.properties[propKeys[k]];
|
|
863
|
+
|
|
864
|
+
// if this key is to a reference
|
|
865
|
+
if (thisProp.$ref) {
|
|
866
|
+
const refs = thisProp.$ref.split('/');
|
|
867
|
+
|
|
868
|
+
// references should be to a sub of another section like definitions
|
|
869
|
+
// like - #/definitions/credentials
|
|
870
|
+
if (refs.length >= 3) {
|
|
871
|
+
// recursive call with reference object
|
|
872
|
+
defaults[propKeys[k]] = this.setDefaults(propSchema[refs[1]][refs[2]]);
|
|
873
|
+
}
|
|
874
|
+
} else if (Object.hasOwnProperty.call(thisProp, 'default')) {
|
|
875
|
+
// if there is a default put into the object
|
|
876
|
+
defaults[propKeys[k]] = thisProp.default;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// return the defaults
|
|
881
|
+
return defaults;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* @summary Takes in properties and the secondary properties and merges them so the returned
|
|
886
|
+
* object has secondary properties where no primary property values were provided.
|
|
887
|
+
*
|
|
888
|
+
* @function mergeProperties
|
|
889
|
+
* @param {Object} properties - the primary propererties (required)
|
|
890
|
+
* @param {Object} secondary - the secondary propererties (required)
|
|
891
|
+
*
|
|
892
|
+
* @return {Object} the properties with the merged in secondaries
|
|
893
|
+
*/
|
|
894
|
+
mergeProperties(properties, secondary) {
|
|
895
|
+
const origin = `${this.myid}-propertyUtil-mergeProperties`;
|
|
896
|
+
log.trace(origin);
|
|
897
|
+
|
|
898
|
+
// verify the input for the method
|
|
899
|
+
if (!properties || typeof properties !== 'object') {
|
|
900
|
+
return secondary;
|
|
901
|
+
}
|
|
902
|
+
if (!secondary || typeof secondary !== 'object') {
|
|
903
|
+
return properties;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
const combinedProps = secondary;
|
|
907
|
+
const propKeys = Object.keys(properties);
|
|
908
|
+
|
|
909
|
+
// loop through all of the primary properties to insert them into the conbined data
|
|
910
|
+
for (let k = 0; k < propKeys.length; k += 1) {
|
|
911
|
+
const thisProp = properties[propKeys[k]];
|
|
912
|
+
|
|
913
|
+
// if this key is to an object
|
|
914
|
+
if (thisProp && typeof thisProp === 'object' && combinedProps[propKeys[k]]) {
|
|
915
|
+
// recursive call with primary and secondary object
|
|
916
|
+
combinedProps[propKeys[k]] = this.mergeProperties(thisProp, combinedProps[propKeys[k]]);
|
|
917
|
+
} else if ((thisProp !== undefined && thisProp !== null && thisProp !== '')
|
|
918
|
+
|| (combinedProps[propKeys[k]] === undefined || combinedProps[propKeys[k]] === null || combinedProps[propKeys[k]] === '')) {
|
|
919
|
+
// if no secondary or primary has value merge it - overriding the secondary
|
|
920
|
+
combinedProps[propKeys[k]] = thisProp;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// return the merged properties
|
|
925
|
+
return combinedProps;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* @summary Takes in property text and an encoding/encryption and returns the resulting
|
|
930
|
+
* encoded/encrypted string
|
|
931
|
+
*
|
|
932
|
+
* @function encryptProperty
|
|
933
|
+
* @param {String} property - the property to encrypt (required)
|
|
934
|
+
* @param {String} technique - the technique to use to encrypt (required)
|
|
935
|
+
*
|
|
936
|
+
* @return {String} the encrypted/encoded string
|
|
937
|
+
*/
|
|
938
|
+
encryptProperty(property, technique) {
|
|
939
|
+
const origin = `${this.myid}-propertyUtil-encryptProperty`;
|
|
940
|
+
log.trace(origin);
|
|
941
|
+
|
|
942
|
+
try {
|
|
943
|
+
// verify the input for the method
|
|
944
|
+
if (!property) {
|
|
945
|
+
return null;
|
|
946
|
+
}
|
|
947
|
+
if (!technique) {
|
|
948
|
+
return property;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// if encoding, return the encoded string
|
|
952
|
+
if (technique.toUpperCase() === 'BASE64') {
|
|
953
|
+
return `{code}${Buffer.from(property).toString('base64')}`;
|
|
954
|
+
}
|
|
955
|
+
// if encrypting, return the encrypted string
|
|
956
|
+
if (technique.toUpperCase() === 'ENCRYPT') {
|
|
957
|
+
return `{crypt}${cryptoJS.AES.encrypt(property, this.myid)}`;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
log.warn(`${origin}: Encyrpt technique ${technique} not supported!`);
|
|
961
|
+
return property;
|
|
962
|
+
} catch (e) {
|
|
963
|
+
log.error(`${origin}: Encyrpt technique ${technique} took exception: ${e}`);
|
|
964
|
+
return null;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/**
|
|
969
|
+
* @summary Takes in encrypted or encoded property and decodes/decrypts it to return
|
|
970
|
+
* the actual property
|
|
971
|
+
*
|
|
972
|
+
* @function decryptProperty
|
|
973
|
+
* @param {String} property - the property to decrypt
|
|
974
|
+
*
|
|
975
|
+
* @return {String} the string
|
|
976
|
+
*/
|
|
977
|
+
decryptProperty(property) {
|
|
978
|
+
const origin = `${this.myid}-propertyUtil-decryptProperty`;
|
|
979
|
+
log.trace(origin);
|
|
980
|
+
|
|
981
|
+
try {
|
|
982
|
+
// verify the input for the method
|
|
983
|
+
if (!property) {
|
|
984
|
+
return null;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
if (property.indexOf('{code}') === 0) {
|
|
988
|
+
// remove the start
|
|
989
|
+
const b64prop = property.substring(6);
|
|
990
|
+
|
|
991
|
+
// decode the string
|
|
992
|
+
return Buffer.from(b64prop, 'base64').toString();
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
if (property.indexOf('{crypt}') === 0) {
|
|
996
|
+
// remove the start
|
|
997
|
+
const cryptprop = property.substring(7);
|
|
998
|
+
|
|
999
|
+
// decrypt the string
|
|
1000
|
+
return cryptoJS.AES.decrypt(cryptprop, this.myid).toString(cryptoJS.enc.Utf8);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
log.warn(`${origin}: Invalid property ${property} - should start with {code} or {crypt}!`);
|
|
1004
|
+
return property;
|
|
1005
|
+
} catch (e) {
|
|
1006
|
+
log.error(`${origin}: Decrypt property took exception: ${e}`);
|
|
1007
|
+
return null;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
module.exports = AdapterPropertyUtil;
|