@itentialopensource/adapter-efficientip_solidserver 0.1.1 → 0.3.0

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.
Files changed (57) hide show
  1. package/AUTH.md +39 -0
  2. package/BROKER.md +199 -0
  3. package/CALLS.md +1465 -0
  4. package/CHANGELOG.md +17 -2
  5. package/CODE_OF_CONDUCT.md +12 -17
  6. package/CONTRIBUTING.md +3 -148
  7. package/ENHANCE.md +69 -0
  8. package/PROPERTIES.md +641 -0
  9. package/README.md +235 -576
  10. package/SUMMARY.md +9 -0
  11. package/SYSTEMINFO.md +11 -0
  12. package/TROUBLESHOOT.md +47 -0
  13. package/adapter.js +383 -263
  14. package/adapterBase.js +854 -408
  15. package/changelogs/changelog.md +16 -0
  16. package/entities/.generic/action.json +110 -5
  17. package/entities/.generic/schema.json +6 -1
  18. package/error.json +6 -0
  19. package/metadata.json +49 -0
  20. package/package.json +27 -22
  21. package/pronghorn.json +691 -88
  22. package/propertiesDecorators.json +14 -0
  23. package/propertiesSchema.json +828 -7
  24. package/refs?service=git-upload-pack +0 -0
  25. package/report/adapter-openapi.json +41906 -0
  26. package/report/adapter-openapi.yaml +23138 -0
  27. package/report/adapterInfo.json +10 -0
  28. package/report/updateReport1653233995404.json +120 -0
  29. package/report/updateReport1691508450223.json +120 -0
  30. package/report/updateReport1692202927301.json +120 -0
  31. package/report/updateReport1694465845842.json +120 -0
  32. package/report/updateReport1698421858198.json +120 -0
  33. package/sampleProperties.json +153 -3
  34. package/test/integration/adapterTestBasicGet.js +3 -5
  35. package/test/integration/adapterTestConnectivity.js +91 -42
  36. package/test/integration/adapterTestIntegration.js +155 -106
  37. package/test/unit/adapterBaseTestUnit.js +388 -308
  38. package/test/unit/adapterTestUnit.js +484 -243
  39. package/utils/adapterInfo.js +206 -0
  40. package/utils/addAuth.js +94 -0
  41. package/utils/artifactize.js +1 -1
  42. package/utils/basicGet.js +1 -14
  43. package/utils/checkMigrate.js +1 -1
  44. package/utils/entitiesToDB.js +179 -0
  45. package/utils/findPath.js +1 -1
  46. package/utils/methodDocumentor.js +273 -0
  47. package/utils/modify.js +14 -16
  48. package/utils/packModificationScript.js +1 -1
  49. package/utils/patches2bundledDeps.js +90 -0
  50. package/utils/pre-commit.sh +5 -0
  51. package/utils/removeHooks.js +20 -0
  52. package/utils/taskMover.js +309 -0
  53. package/utils/tbScript.js +129 -53
  54. package/utils/tbUtils.js +125 -25
  55. package/utils/testRunner.js +17 -17
  56. package/utils/troubleshootingAdapter.js +10 -31
  57. package/workflows/README.md +0 -3
package/utils/tbUtils.js CHANGED
@@ -3,10 +3,11 @@
3
3
  /* eslint import/no-extraneous-dependencies: warn */
4
4
  /* eslint global-require: warn */
5
5
  /* eslint import/no-dynamic-require: warn */
6
+ /* eslint-disable no-console */
6
7
 
7
8
  const path = require('path');
8
- const fs = require('fs-extra');
9
9
  const cp = require('child_process');
10
+ const fs = require('fs-extra');
10
11
 
11
12
  module.exports = {
12
13
  SERVICE_CONFIGS_COLLECTION: 'service_configs',
@@ -100,10 +101,8 @@ module.exports = {
100
101
  *
101
102
  * @function decryptProperties
102
103
  */
103
- decryptProperties: (props, dirname, discovery) => {
104
- const propertyEncryptionClassPath = path.join(dirname, '../../../@itential/pronghorn-core/core/PropertyEncryption.js');
105
- const isEncrypted = props.pathProps.encrypted;
106
- const PropertyEncryption = discovery.require(propertyEncryptionClassPath, isEncrypted);
104
+ decryptProperties: (props, iapDir) => {
105
+ const { PropertyEncryption } = require(path.join(iapDir, 'node_modules/@itential/itential-utils'));
107
106
  const propertyEncryption = new PropertyEncryption({
108
107
  algorithm: 'aes-256-ctr',
109
108
  key: 'TG9uZ0Rpc3RhbmNlUnVubmVyUHJvbmdob3JuCg==',
@@ -159,8 +158,7 @@ module.exports = {
159
158
  * @param {Object} healthcheck - {Object} healthcheck - ./entities/.system/action.json object
160
159
  */
161
160
  getHealthCheckEndpoint: (healthcheck) => {
162
- const endpoint = healthcheck.actions[1].entitypath.slice(21,
163
- healthcheck.actions[1].entitypath.length - 8);
161
+ const endpoint = healthcheck.actions[1].entitypath.slice(21, healthcheck.actions[1].entitypath.length - 8);
164
162
  return { healthCheckEndpoint: endpoint };
165
163
  },
166
164
 
@@ -177,12 +175,12 @@ module.exports = {
177
175
  verifyInstallationDir: (dirname, name) => {
178
176
  const pathArray = dirname.split(path.sep);
179
177
  const expectedPath = `node_modules/${name}`;
180
- const currentPath = pathArray.slice(pathArray.length - 4, pathArray.length - 1).join('/');
181
- if (expectedPath !== currentPath) {
182
- throw new Error(`adapter should be installed under ${expectedPath}`);
178
+ const currentPath = pathArray.slice(pathArray.length - 3, pathArray.length).join('/');
179
+ if (currentPath.trim() !== expectedPath.trim()) {
180
+ throw new Error(`adapter should be installed under ${expectedPath} but is installed under ${currentPath}`);
183
181
  }
184
182
 
185
- const serverFile = path.join(dirname, '../../../..', 'server.js');
183
+ const serverFile = path.join(dirname, '../../../', 'server.js');
186
184
  if (!fs.existsSync(serverFile)) {
187
185
  throw new Error(`adapter should be installed under IAP/${expectedPath}`);
188
186
  }
@@ -202,6 +200,7 @@ module.exports = {
202
200
  try {
203
201
  stdout = cp.execSync(cmd).toString();
204
202
  } catch (error) {
203
+ console.log('execute command error', error.stdout.toString(), error.stderr.toString());
205
204
  stdout = error.stdout.toString();
206
205
  }
207
206
  const output = this.getTestCount(stdout);
@@ -289,10 +288,12 @@ module.exports = {
289
288
  */
290
289
  runConnectivity: function runConnectivity(host, scriptFlag) {
291
290
  let testPath = 'test/integration/adapterTestConnectivity.js';
291
+ let executable = 'mocha';
292
292
  if (!scriptFlag) {
293
293
  testPath = path.resolve(__dirname, '..', testPath);
294
+ executable = path.join(__dirname, '..', 'node_modules/mocha/bin/mocha');
294
295
  }
295
- return this.systemSync(`mocha ${testPath} --HOST=${host} --timeout 10000 --exit`, !scriptFlag);
296
+ return this.systemSync(`${executable} ${testPath} --HOST=${host} --timeout 10000 --exit`, !scriptFlag);
296
297
  },
297
298
 
298
299
  /**
@@ -304,9 +305,10 @@ module.exports = {
304
305
  * @param {Object} adapterPronghorn - ./pronghorn.json in adapter dir
305
306
  * @param {Object} sampleProperties - './sampleProperties.json' in adapter dir
306
307
  */
307
- createAdapter: (pronghornProps, profileItem, sampleProperties, adapterPronghorn) => {
308
- const packagePath = `${__dirname.split('node_modules')[0]}package.json`;
309
- const info = JSON.parse(fs.readFileSync(packagePath));
308
+ createAdapter: function createAdapter(pronghornProps, profileItem, sampleProperties, adapterPronghorn) {
309
+ const iapDir = this.getIAPHome();
310
+ const packageFile = path.join(iapDir, 'package.json');
311
+ const info = JSON.parse(fs.readFileSync(packageFile));
310
312
  const version = parseInt(info.version.split('.')[0], 10);
311
313
 
312
314
  let adapter = {};
@@ -338,6 +340,45 @@ module.exports = {
338
340
  return adapter;
339
341
  },
340
342
 
343
+ getPronghornProps: function getPronghornProps() {
344
+ const iapDir = this.getIAPHome();
345
+ console.log('Retrieving properties.json file...');
346
+ const rawProps = require(path.join(iapDir, 'properties.json'));
347
+ console.log('Decrypting properties...');
348
+ const pronghornProps = this.decryptProperties(rawProps, iapDir);
349
+ console.log('Found properties.\n');
350
+ return pronghornProps;
351
+ },
352
+
353
+ getAllAdapterInstances: async function getAllAdapterInstances() {
354
+ const database = await this.getIAPDatabaseConnection();
355
+ const { name } = require(path.join(__dirname, '..', 'package.json'));
356
+ const query = { model: name };
357
+ const options = { projection: { name: 1 } };
358
+ const adapterInstancesNames = await database.collection(this.SERVICE_CONFIGS_COLLECTION).find(
359
+ query,
360
+ options
361
+ ).toArray();
362
+ return adapterInstancesNames;
363
+ },
364
+
365
+ // get database connection and existing adapter config
366
+ getAdapterConfig: async function getAdapterConfig(adapterId) {
367
+ const database = await this.getIAPDatabaseConnection();
368
+ const { name } = require(path.join(__dirname, '..', 'package.json'));
369
+ let query = {};
370
+ if (!adapterId) {
371
+ query = { model: name };
372
+ } else {
373
+ query = { _id: adapterId };
374
+ }
375
+ const serviceItem = await database.collection(this.SERVICE_CONFIGS_COLLECTION).findOne(
376
+ query
377
+ );
378
+ const pronghornProps = await this.getPronghornProps();
379
+ return { database, serviceItem, pronghornProps };
380
+ },
381
+
341
382
  /**
342
383
  * @summary return async healthcheck result as a Promise
343
384
  *
@@ -373,17 +414,76 @@ module.exports = {
373
414
  },
374
415
 
375
416
  /**
376
- * @summary Check whether adapter is located within IAP node_modules
377
- * by loading properties.json. If not, return false.
378
- * @function withinIAP
379
- * @param {String} iapDir root directory of IAP
417
+ * @summary Obtain the IAP installation directory depending on how adapter is used:
418
+ * by IAP, or by npm run CLI interface
419
+ * @returns IAP installation directory or null if adapter running without IAP
420
+ * @function getIAPHome
380
421
  */
381
- withinIAP: (iapDir) => {
382
- try {
383
- const rawProps = require(path.join(iapDir, 'properties.json'));
384
- return rawProps;
385
- } catch (error) {
386
- return false;
422
+ getIAPHome: function getIAPHome() {
423
+ let IAPHomePath = null;
424
+ // check if adapter started via IAP, use path injected by core
425
+ if (process.env.iap_home) IAPHomePath = process.env.iap_home;
426
+ // check if adapter started via CLI `npm run <command>` so we have to be located under
427
+ // <IAP_HOME>/node_modules/@itentialopensource/<adapter_name>/ directory
428
+ const currentExecutionPath = this.getCurrentExecutionPath();
429
+ if (currentExecutionPath.indexOf('/node_modules') >= 0) {
430
+ [IAPHomePath] = currentExecutionPath.split('/node_modules');
431
+ }
432
+ return IAPHomePath;
433
+ },
434
+
435
+ /**
436
+ * @summary get current execution path without resolving symbolic links,
437
+ * use `pwd` command wihout '-P' option (resolving symlinks) https://linux.die.net/man/1/pwd
438
+ * @returns
439
+ * @function getCurrentExecutionPAth
440
+ */
441
+ getCurrentExecutionPath: function getCurrentExecutionPAth() {
442
+ const { stdout } = this.systemSync('pwd', true);
443
+ return stdout.trim();
444
+ },
445
+
446
+ /**
447
+ * @summary checks if command executed from <IAP_HOME>/node_modules/@itentialopensource/<adapter_name>/ location
448
+ * @returns true if command executed under <IAP_HOME>/node_modules/@itentialopensource/<adapter_name>/ path
449
+ * @function areWeUnderIAPinstallationDirectory
450
+ */
451
+ areWeUnderIAPinstallationDirectory: function areWeUnderIAPinstallationDirectory() {
452
+ return path.join(this.getCurrentExecutionPath(), '../../..') === this.getIAPHome();
453
+ },
454
+
455
+ getIAPDatabaseConnection: async function getIAPDatabaseConnection() {
456
+ const pronghornProps = await this.getPronghornProps();
457
+ const database = await this.connect(pronghornProps);
458
+ return database;
459
+ },
460
+
461
+ /**
462
+ * @summary connect to mongodb
463
+ *
464
+ * @function connect
465
+ * @param {Object} properties - pronghornProps
466
+ */
467
+ connect: async function connect(properties) {
468
+ let dbConnectionProperties = {};
469
+ if (properties.mongoProps) {
470
+ dbConnectionProperties = properties.mongoProps;
471
+ } else if (properties.mongo) {
472
+ if (properties.mongo.url) {
473
+ dbConnectionProperties.url = properties.mongo.url;
474
+ } else {
475
+ dbConnectionProperties.url = `mongodb://${properties.mongo.host}:${properties.mongo.port}`;
476
+ }
477
+ dbConnectionProperties.db = properties.mongo.database;
387
478
  }
479
+ if (!dbConnectionProperties.url || !dbConnectionProperties.db) {
480
+ throw new Error('Mongo properties are not specified in IAP configuration!');
481
+ }
482
+ const iapDir = this.getIAPHome();
483
+ const { MongoDBConnection } = require(path.join(iapDir, 'node_modules/@itential/database'));
484
+ const connection = new MongoDBConnection(dbConnectionProperties);
485
+ const database = await connection.connect(true);
486
+ return database;
388
487
  }
488
+
389
489
  };
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  /* @copyright Itential, LLC 2019 */
3
3
 
4
+ const execute = require('child_process').exec;
4
5
  const fs = require('fs-extra');
5
6
  const rl = require('readline-sync');
6
- const execute = require('child_process').exec;
7
7
 
8
8
  /**
9
9
  * This script will determine the type of integration test to run
@@ -47,11 +47,11 @@ function replaceTestVars(test) {
47
47
  let intTest = fs.readFileSync(test, 'utf8');
48
48
 
49
49
  // replace stub variable but check if it exists first
50
- let sindex = intTest.indexOf('const stub');
50
+ let sindex = intTest.indexOf('samProps.stub');
51
51
  let eindex = intTest.indexOf(';', sindex);
52
52
  let replStr = intTest.substring(sindex, eindex + 1);
53
53
  if (sindex > -1) {
54
- intTest = intTest.replace(replStr, `const stub = ${stub};`);
54
+ intTest = intTest.replace(replStr, `samProps.stub = ${stub};`);
55
55
  }
56
56
 
57
57
  // replace isRapidFail variable but check if it exists first
@@ -71,46 +71,46 @@ function replaceTestVars(test) {
71
71
  }
72
72
 
73
73
  // replace host variable
74
- sindex = intTest.indexOf('const host');
74
+ sindex = intTest.indexOf('samProps.host');
75
75
  eindex = intTest.indexOf(';', sindex);
76
76
  replStr = intTest.substring(sindex, eindex + 1);
77
- intTest = intTest.replace(replStr, `const host = '${host}';`);
77
+ intTest = intTest.replace(replStr, `samProps.host = '${host}';`);
78
78
 
79
79
  // replace username variable
80
- sindex = intTest.indexOf('const username');
80
+ sindex = intTest.indexOf('samProps.authentication.username');
81
81
  eindex = intTest.indexOf(';', sindex);
82
82
  replStr = intTest.substring(sindex, eindex + 1);
83
- intTest = intTest.replace(replStr, `const username = '${username}';`);
83
+ intTest = intTest.replace(replStr, `samProps.authentication.username = '${username}';`);
84
84
 
85
85
  // replace password variable
86
- sindex = intTest.indexOf('const password');
86
+ sindex = intTest.indexOf('samProps.authentication.password');
87
87
  eindex = intTest.indexOf(';', sindex);
88
88
  replStr = intTest.substring(sindex, eindex + 1);
89
- intTest = intTest.replace(replStr, `const password = '${password}';`);
89
+ intTest = intTest.replace(replStr, `samProps.authentication.password = '${password}';`);
90
90
 
91
91
  // replace protocol variable
92
- sindex = intTest.indexOf('const protocol');
92
+ sindex = intTest.indexOf('samProps.protocol');
93
93
  eindex = intTest.indexOf(';', sindex);
94
94
  replStr = intTest.substring(sindex, eindex + 1);
95
- intTest = intTest.replace(replStr, `const protocol = '${protocol}';`);
95
+ intTest = intTest.replace(replStr, `samProps.protocol = '${protocol}';`);
96
96
 
97
97
  // replace port variable
98
- sindex = intTest.indexOf('const port');
98
+ sindex = intTest.indexOf('samProps.port');
99
99
  eindex = intTest.indexOf(';', sindex);
100
100
  replStr = intTest.substring(sindex, eindex + 1);
101
- intTest = intTest.replace(replStr, `const port = ${port};`);
101
+ intTest = intTest.replace(replStr, `samProps.port = ${port};`);
102
102
 
103
103
  // replace sslenable variable
104
- sindex = intTest.indexOf('const sslenable');
104
+ sindex = intTest.indexOf('samProps.ssl.enabled');
105
105
  eindex = intTest.indexOf(';', sindex);
106
106
  replStr = intTest.substring(sindex, eindex + 1);
107
- intTest = intTest.replace(replStr, `const sslenable = ${sslenable};`);
107
+ intTest = intTest.replace(replStr, `samProps.ssl.enabled = ${sslenable};`);
108
108
 
109
109
  // replace sslinvalid variable
110
- sindex = intTest.indexOf('const sslinvalid');
110
+ sindex = intTest.indexOf('samProps.ssl.accept_invalid_cert');
111
111
  eindex = intTest.indexOf(';', sindex);
112
112
  replStr = intTest.substring(sindex, eindex + 1);
113
- intTest = intTest.replace(replStr, `const sslinvalid = ${sslinvalid};`);
113
+ intTest = intTest.replace(replStr, `samProps.ssl.accept_invalid_cert = ${sslinvalid};`);
114
114
 
115
115
  console.log(`Updates to ${test} complete`);
116
116
  fs.writeFileSync(test, intTest);
@@ -117,30 +117,6 @@ const VerifyHealthCheckEndpoint = (serviceItem, props, scriptFlag) => {
117
117
  return { result, updatedAdapter };
118
118
  };
119
119
 
120
- const getPronghornProps = (iapDir) => {
121
- console.log('Retrieving properties.json file...');
122
- const rawProps = require(path.join(iapDir, 'properties.json'));
123
- console.log('Decrypting properties...');
124
- const { Discovery } = require('@itential/itential-utils');
125
- const discovery = new Discovery();
126
- const pronghornProps = utils.decryptProperties(rawProps, __dirname, discovery);
127
- console.log('Found properties.\n');
128
- return pronghornProps;
129
- };
130
-
131
- // get database connection and existing adapter config
132
- const getAdapterConfig = async () => {
133
- const iapDir = path.join(__dirname, '../../../../');
134
- const pronghornProps = getPronghornProps(iapDir);
135
- console.log('Connecting to Database...');
136
- const database = await basicGet.connect(pronghornProps);
137
- console.log('Connection established.');
138
- const serviceItem = await database.collection(utils.SERVICE_CONFIGS_COLLECTION).findOne(
139
- { model: name }
140
- );
141
- return { database, serviceItem, pronghornProps };
142
- };
143
-
144
120
  const offline = async () => {
145
121
  console.log('Start offline troubleshooting');
146
122
  const { updatedAdapter } = VerifyHealthCheckEndpoint({ properties: sampleProperties }, {}, true);
@@ -158,9 +134,13 @@ const offline = async () => {
158
134
  };
159
135
 
160
136
  const troubleshoot = async (props, scriptFlag, persistFlag, adapter) => {
161
- // get database connection and existing adapter config
162
- const { database, serviceItem } = await getAdapterConfig();
163
- // where troubleshoot should start
137
+ let serviceItem;
138
+ if (adapter && adapter.allProps) {
139
+ serviceItem = { properties: { properties: adapter.allProps } };
140
+ }
141
+ if (adapter && adapter.properties && adapter.properties.properties) {
142
+ serviceItem = adapter.properties;
143
+ }
164
144
  if (serviceItem) {
165
145
  if (!scriptFlag || rls.keyInYN(`Start verifying the connection and authentication properties for ${name}?`)) {
166
146
  const { result, updatedAdapter } = VerifyHealthCheckEndpoint(serviceItem, props, scriptFlag);
@@ -178,10 +158,9 @@ const troubleshoot = async (props, scriptFlag, persistFlag, adapter) => {
178
158
  }
179
159
 
180
160
  if (persistFlag && healthRes) {
161
+ const { database } = await utils.getIAPDatabaseConnection();
181
162
  const update = { $set: { properties: updatedAdapter.properties } };
182
- await database.collection(utils.SERVICE_CONFIGS_COLLECTION).updateOne(
183
- { model: name }, update
184
- );
163
+ await database.collection(utils.SERVICE_CONFIGS_COLLECTION).updateOne({ model: name }, update);
185
164
  if (scriptFlag) {
186
165
  console.log(`${name} updated.`);
187
166
  }
@@ -211,4 +190,4 @@ const troubleshoot = async (props, scriptFlag, persistFlag, adapter) => {
211
190
  return null;
212
191
  };
213
192
 
214
- module.exports = { troubleshoot, getAdapterConfig, offline };
193
+ module.exports = { troubleshoot, offline };
@@ -1,3 +0,0 @@
1
- # Adapter Workflows
2
-
3
- This directory contains workflows that support the adapter use cases. These workflows can be imported into IAP. If the adapter is installed using App-Artifact the workflows should be automatically imported.