mybase 1.1.1 → 1.1.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/mybase.js +5 -6
- package/package.json +4 -2
- package/ts/funcs/asJSON.test.js +72 -0
- package/ts/funcs/asJSON.ts +6 -0
- package/ts/funcs/fileCacheIsValid.js +39 -0
- package/ts/funcs/fileCacheIsValid.ts +13 -0
- package/ts/funcs/hash_sha512.js +10 -0
- package/ts/funcs/hash_sha512.ts +7 -0
- package/ts/funcs/promiseTimeout.test.js +104 -0
- package/ts/funcs/promiseTimeout.ts +19 -0
- package/ts/funcs/vaultFill.js +96 -0
- package/ts/funcs/vaultFill.ts +89 -0
- package/ts/funcs/vaultRead.js +51 -0
- package/ts/funcs/vaultRead.ts +45 -0
- package/ts/funcs/wait.d.ts +1 -0
- package/ts/funcs/wait.js +9 -0
- package/ts/funcs/wait.ts +7 -0
- package/ts/global.js +15 -0
- package/ts/global.ts +10 -0
- package/ts/index.d.ts +1 -0
- package/ts/index.js +5 -0
- package/ts/index.test.ts +3 -5
- package/ts/index.ts +7 -1
package/mybase.js
CHANGED
|
@@ -7,7 +7,6 @@ const net = require('net')
|
|
|
7
7
|
const chalk = require('chalk')
|
|
8
8
|
const punycode = require('punycode');
|
|
9
9
|
const _validURL = require('@7c/validurl')
|
|
10
|
-
const { match } = require('assert');
|
|
11
10
|
const validator = require('validator')
|
|
12
11
|
const sha512 = require('js-sha512')
|
|
13
12
|
const ip6addr = require('ip6addr')
|
|
@@ -116,7 +115,7 @@ function utcnow() { // ported
|
|
|
116
115
|
return Math.floor(Date.now() / 1000)
|
|
117
116
|
}
|
|
118
117
|
|
|
119
|
-
function validIp(str) {
|
|
118
|
+
function validIp(str) { // ported
|
|
120
119
|
if (str && typeof str==='string') {
|
|
121
120
|
let splitted
|
|
122
121
|
if (splitted=str.match(/^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$/)) {
|
|
@@ -178,7 +177,7 @@ function validURL(host) {
|
|
|
178
177
|
return _validURL(host)
|
|
179
178
|
}
|
|
180
179
|
|
|
181
|
-
function asJSON(str) {
|
|
180
|
+
function asJSON(str) { // ported
|
|
182
181
|
if (!str || typeof str!=='string') return false
|
|
183
182
|
try { return JSON.parse(str)}catch(_) {}
|
|
184
183
|
return false
|
|
@@ -263,7 +262,7 @@ function vaultRead(vault, key, cache_in_minutes = 10) {
|
|
|
263
262
|
}
|
|
264
263
|
|
|
265
264
|
|
|
266
|
-
function vaultFill(vault, obj, ignoreError = false, keepCache=true) {
|
|
265
|
+
function vaultFill(vault, obj, ignoreError = false, keepCache=true) { // ported
|
|
267
266
|
// v2.1
|
|
268
267
|
// fills all strings with ^vault@/secret/... with proper vault values
|
|
269
268
|
// if you call it again, it does reload the configuration
|
|
@@ -557,7 +556,7 @@ function sqlQuery(sqlHandle,query,values=[]) {
|
|
|
557
556
|
})
|
|
558
557
|
}
|
|
559
558
|
|
|
560
|
-
function wait(seconds=1){
|
|
559
|
+
function wait(seconds=1){ // ported
|
|
561
560
|
return new Promise((resolve,reject)=>{
|
|
562
561
|
setTimeout(resolve,seconds*1000)
|
|
563
562
|
})
|
|
@@ -574,7 +573,7 @@ function validUUID4(uuid) {
|
|
|
574
573
|
return new RegExp(/^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i).test(uuid)
|
|
575
574
|
}
|
|
576
575
|
|
|
577
|
-
function promiseTimeout(ms, promise) {
|
|
576
|
+
function promiseTimeout(ms, promise) { // ported
|
|
578
577
|
// Create a promise that rejects in <ms> milliseconds
|
|
579
578
|
let timeout = new Promise((resolve, reject) => {
|
|
580
579
|
let id = setTimeout(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mybase",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "mybase.js",
|
|
6
6
|
"scripts": {
|
|
@@ -12,17 +12,19 @@
|
|
|
12
12
|
"@7c/validurl": "0.0.3",
|
|
13
13
|
"aes-js": "^3.1.2",
|
|
14
14
|
"chalk": "^3.0.0",
|
|
15
|
-
"debug": "^4.3.
|
|
15
|
+
"debug": "^4.3.4",
|
|
16
16
|
"ip-range-check": "^0.2.0",
|
|
17
17
|
"ip6": "=0.2.7",
|
|
18
18
|
"ip6addr": "^0.2.5",
|
|
19
19
|
"js-sha512": "^0.8.0",
|
|
20
|
+
"node-vault": "^0.10.2",
|
|
20
21
|
"psl": "^1.9.0",
|
|
21
22
|
"punycode": "^2.1.1",
|
|
22
23
|
"validator": "^13.7.0"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@jest/globals": "^29.7.0",
|
|
27
|
+
"@types/debug": "^4.1.12",
|
|
26
28
|
"@types/jest": "^29.5.11",
|
|
27
29
|
"@types/node": "^20.11.5",
|
|
28
30
|
"chai": "^4.2.0",
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const { asJSON } = require('./asJSON')
|
|
2
|
+
|
|
3
|
+
describe('asJSON', () => {
|
|
4
|
+
// Returns parsed JSON object when valid JSON string is passed as input.
|
|
5
|
+
it('should return parsed JSON object when valid JSON string is passed as input', () => {
|
|
6
|
+
const inputString = '{"name": "John", "age": 30}';
|
|
7
|
+
const expectedOutput = { name: "John", age: 30 };
|
|
8
|
+
const result = asJSON(inputString);
|
|
9
|
+
expect(result).toEqual(expectedOutput);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// Returns false when empty string is passed as input.
|
|
13
|
+
it('should return false when empty string is passed as input', () => {
|
|
14
|
+
const inputString = "";
|
|
15
|
+
const expectedOutput = false;
|
|
16
|
+
const result = asJSON(inputString);
|
|
17
|
+
expect(result).toEqual(expectedOutput);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Returns false when non-string input is passed.
|
|
21
|
+
it('should return false when non-string input is passed', () => {
|
|
22
|
+
const inputString = 123;
|
|
23
|
+
const expectedOutput = false;
|
|
24
|
+
const result = asJSON(inputString);
|
|
25
|
+
expect(result).toEqual(expectedOutput);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Returns false when null is passed as input.
|
|
29
|
+
it('should return false when null is passed as input', () => {
|
|
30
|
+
const inputString = null;
|
|
31
|
+
const expectedOutput = false;
|
|
32
|
+
const result = asJSON(inputString);
|
|
33
|
+
expect(result).toEqual(expectedOutput);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Returns false when undefined is passed as input.
|
|
37
|
+
it('should return false when undefined is passed as input', () => {
|
|
38
|
+
const inputString = undefined;
|
|
39
|
+
const expectedOutput = false;
|
|
40
|
+
const result = asJSON(inputString);
|
|
41
|
+
expect(result).toEqual(expectedOutput);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Returns false when NaN is passed as input.
|
|
45
|
+
it('should return false when NaN is passed as input', () => {
|
|
46
|
+
const inputString = NaN;
|
|
47
|
+
const expectedOutput = false;
|
|
48
|
+
const result = asJSON(inputString);
|
|
49
|
+
expect(result).toEqual(expectedOutput);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Returns false when invalid JSON string is passed as input.
|
|
53
|
+
it('should return false when invalid JSON string is passed as input', () => {
|
|
54
|
+
const inputString = 'invalid json';
|
|
55
|
+
const result = asJSON(inputString);
|
|
56
|
+
expect(result).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Returns false when Infinity is passed as input.
|
|
60
|
+
it('should return false when Infinity is passed as input', () => {
|
|
61
|
+
const inputString = 'Infinity';
|
|
62
|
+
const result = asJSON(inputString);
|
|
63
|
+
expect(result).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Returns false when input string contains a single quote.
|
|
67
|
+
it('should return false when input string contains a single quote', () => {
|
|
68
|
+
const inputString = "{'name': 'John'}";
|
|
69
|
+
const result = asJSON(inputString);
|
|
70
|
+
expect(result).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.fileCacheIsValid = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
function fileCacheIsValid(cacheFileName, cache_in_minutes = 60) {
|
|
29
|
+
if (fs.existsSync(cacheFileName)) {
|
|
30
|
+
const stat = fs.statSync(cacheFileName);
|
|
31
|
+
const mtime = new Date(stat.mtime).getTime();
|
|
32
|
+
if (Date.now() - mtime < cache_in_minutes * 60 * 1000) {
|
|
33
|
+
// cache is still valid
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
exports.fileCacheIsValid = fileCacheIsValid;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as fs from 'fs'
|
|
2
|
+
|
|
3
|
+
export function fileCacheIsValid(cacheFileName : string, cache_in_minutes = 60) : boolean {
|
|
4
|
+
if (fs.existsSync(cacheFileName)) {
|
|
5
|
+
const stat = fs.statSync(cacheFileName)
|
|
6
|
+
const mtime = new Date(stat.mtime).getTime()
|
|
7
|
+
if (Date.now() - mtime < cache_in_minutes * 60 * 1000) {
|
|
8
|
+
// cache is still valid
|
|
9
|
+
return true
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hash_sha512 = void 0;
|
|
4
|
+
const js_sha512_1 = require("js-sha512");
|
|
5
|
+
function hash_sha512(plainString) {
|
|
6
|
+
if (typeof plainString === 'string')
|
|
7
|
+
return (0, js_sha512_1.sha512)(plainString);
|
|
8
|
+
return "";
|
|
9
|
+
}
|
|
10
|
+
exports.hash_sha512 = hash_sha512;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const { promiseTimeout } = require('./promiseTimeout');
|
|
2
|
+
|
|
3
|
+
describe('promiseTimeout', () => {
|
|
4
|
+
|
|
5
|
+
// Returns a promise that resolves when inputPromise resolves before the timeout.
|
|
6
|
+
it('should resolve when inputPromise resolves before the timeout', () => {
|
|
7
|
+
// Arrange
|
|
8
|
+
const inputPromise = new Promise((resolve) => {
|
|
9
|
+
setTimeout(() => {
|
|
10
|
+
resolve('Resolved');
|
|
11
|
+
}, 100);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// Act
|
|
15
|
+
const resultPromise = promiseTimeout(200, inputPromise);
|
|
16
|
+
|
|
17
|
+
// Assert
|
|
18
|
+
return expect(resultPromise).resolves.toBe('Resolved');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Returns a promise that rejects with onTimeout when inputPromise rejects after the timeout.
|
|
22
|
+
it('should reject with onTimeout when inputPromise rejects after the timeout', () => {
|
|
23
|
+
// Arrange
|
|
24
|
+
const inputPromise = new Promise((resolve, reject) => {
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
reject('Rejected');
|
|
27
|
+
}, 200);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Act
|
|
31
|
+
const resultPromise = promiseTimeout(100, inputPromise);
|
|
32
|
+
|
|
33
|
+
// Assert
|
|
34
|
+
return expect(resultPromise).rejects.toBe('TIMEDOUT');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Returns a promise that rejects with onTimeout when inputPromise is pending after the timeout.
|
|
38
|
+
it('should reject with onTimeout when inputPromise is pending after the timeout', () => {
|
|
39
|
+
// Arrange
|
|
40
|
+
const inputPromise = new Promise(() => { });
|
|
41
|
+
|
|
42
|
+
// Act
|
|
43
|
+
const resultPromise = promiseTimeout(100, inputPromise);
|
|
44
|
+
|
|
45
|
+
// Assert
|
|
46
|
+
return expect(resultPromise).rejects.toBe('TIMEDOUT');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Returns a promise that resolves with inputPromise value when inputPromise resolves before the timeout.
|
|
50
|
+
it('should resolve with inputPromise value when inputPromise resolves before the timeout', () => {
|
|
51
|
+
// Arrange
|
|
52
|
+
const inputPromise = new Promise((resolve) => {
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
resolve('Resolved');
|
|
55
|
+
}, 100);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Act
|
|
59
|
+
const resultPromise = promiseTimeout(200, inputPromise);
|
|
60
|
+
|
|
61
|
+
// Assert
|
|
62
|
+
return expect(resultPromise).resolves.toBe('Resolved');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Returns a promise that rejects with inputPromise value when inputPromise rejects before the timeout.
|
|
66
|
+
it('should reject with inputPromise value when inputPromise rejects before the timeout', () => {
|
|
67
|
+
// Arrange
|
|
68
|
+
const inputPromise = new Promise((resolve, reject) => {
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
reject('Rejected');
|
|
71
|
+
}, 100);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Act
|
|
75
|
+
const resultPromise = promiseTimeout(200, inputPromise);
|
|
76
|
+
|
|
77
|
+
// Assert
|
|
78
|
+
return expect(resultPromise).rejects.toBe('Rejected');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Returns a promise that rejects with inputPromise value when inputPromise is pending before the timeout.
|
|
82
|
+
it('should reject with inputPromise value when inputPromise is pending before the timeout', () => {
|
|
83
|
+
// Arrange
|
|
84
|
+
const inputPromise = new Promise(() => { });
|
|
85
|
+
|
|
86
|
+
// Act
|
|
87
|
+
const resultPromise = promiseTimeout(200, inputPromise);
|
|
88
|
+
|
|
89
|
+
// Assert
|
|
90
|
+
return expect(resultPromise).rejects.toBe('TIMEDOUT');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Returns a promise that resolves with undefined when inputPromise is undefined.
|
|
94
|
+
it('should resolve with undefined when inputPromise is undefined', () => {
|
|
95
|
+
// Arrange
|
|
96
|
+
const inputPromise = undefined;
|
|
97
|
+
|
|
98
|
+
// Act
|
|
99
|
+
const resultPromise = promiseTimeout(200, inputPromise);
|
|
100
|
+
|
|
101
|
+
// Assert
|
|
102
|
+
return expect(resultPromise).resolves.toBe(undefined);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export function promiseTimeout(miliseconds:number, inputPromise:Promise<any>, onTimeout:any='TIMEDOUT') { // ported
|
|
6
|
+
// Create a promise that rejects in <miliseconds> milliseconds
|
|
7
|
+
let timeout = new Promise((resolve, reject) => {
|
|
8
|
+
let stID = setTimeout(() => {
|
|
9
|
+
clearTimeout(stID);
|
|
10
|
+
reject(onTimeout)
|
|
11
|
+
}, miliseconds)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
// Returns a race between our timeout and the passed in promise
|
|
15
|
+
return Promise.race([
|
|
16
|
+
inputPromise,
|
|
17
|
+
timeout
|
|
18
|
+
])
|
|
19
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.vaultFill = void 0;
|
|
13
|
+
const debug_1 = require("debug");
|
|
14
|
+
const vaultRead_1 = require("./vaultRead");
|
|
15
|
+
const dbg = (0, debug_1.debug)('vaultFill');
|
|
16
|
+
function vaultFill(vaultInstance, inputObject, ignoreError = false, keepCache = true) {
|
|
17
|
+
// v2.1
|
|
18
|
+
// fills all strings with ^vault@/secret/... with proper vault values
|
|
19
|
+
// if you call it again, it does reload the configuration
|
|
20
|
+
// v2.2
|
|
21
|
+
// supports keepCache - if vault fails, we will keep previous values instead of filling with false
|
|
22
|
+
return new Promise(function (resolve, reject) {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
let vaultKeys = Array();
|
|
25
|
+
let vaultResults = {};
|
|
26
|
+
findVaultKeyMappings(inputObject, vaultKeys);
|
|
27
|
+
// read these keys from vault
|
|
28
|
+
for (let idx in vaultKeys) {
|
|
29
|
+
const val = vaultKeys[idx];
|
|
30
|
+
if (typeof val !== "string")
|
|
31
|
+
continue;
|
|
32
|
+
try {
|
|
33
|
+
let got = yield (0, vaultRead_1.vaultRead)(vaultInstance, vaultKeys[idx]);
|
|
34
|
+
got['__vaultkey'] = val;
|
|
35
|
+
got['__vaultfilled'] = Date.now();
|
|
36
|
+
vaultResults[val] = got;
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
dbg(`Could not read vaultKey '${val}'`, err);
|
|
40
|
+
if (!ignoreError)
|
|
41
|
+
vaultResults[val] = false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
fillVaultKeyMappings(inputObject, vaultResults, keepCache);
|
|
45
|
+
resolve(true);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
exports.vaultFill = vaultFill;
|
|
50
|
+
function findVaultKeyMappings(config, keys = Array()) {
|
|
51
|
+
for (var i in config) {
|
|
52
|
+
if (config[i] !== null) {
|
|
53
|
+
if (typeof config[i] === 'object' && (config[i].constructor.name === 'Array' || config[i].constructor.name === 'Object'))
|
|
54
|
+
findVaultKeyMappings(config[i], keys);
|
|
55
|
+
// detect previously read vaultKey
|
|
56
|
+
if (i === '__vaultkey') {
|
|
57
|
+
if (!keys.includes(vaultKey))
|
|
58
|
+
keys.push(config[i]);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// --
|
|
62
|
+
if (typeof config[i] === 'string' && config[i].search(/^vault@/) == 0) {
|
|
63
|
+
var splitted = config[i].split(/vault@/);
|
|
64
|
+
if (splitted.length == 2) {
|
|
65
|
+
var vaultKey = splitted[1];
|
|
66
|
+
if (!keys.includes(vaultKey))
|
|
67
|
+
keys.push(vaultKey);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function fillVaultKeyMappings(config, vaultResults, keepCache = true) {
|
|
74
|
+
for (var i in config) {
|
|
75
|
+
if (config[i] !== null) {
|
|
76
|
+
if (config[i] && config[i].constructor.name === 'Object' && config[i].hasOwnProperty('__vaultkey')) {
|
|
77
|
+
if (keepCache) {
|
|
78
|
+
if (vaultResults[config[i]['__vaultkey']])
|
|
79
|
+
config[i] = vaultResults[config[i]['__vaultkey']];
|
|
80
|
+
}
|
|
81
|
+
else
|
|
82
|
+
config[i] = vaultResults[config[i]['__vaultkey']];
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (typeof config[i] === 'object' && (config[i].constructor.name === 'Array' || config[i].constructor.name === 'Object'))
|
|
86
|
+
fillVaultKeyMappings(config[i], vaultResults);
|
|
87
|
+
if (typeof config[i] === 'string' && config[i].search(/^vault@/) == 0) {
|
|
88
|
+
var splitted = config[i].split(/vault@/);
|
|
89
|
+
if (splitted.length == 2) {
|
|
90
|
+
var vaultKey = splitted[1];
|
|
91
|
+
config[i] = vaultResults[vaultKey];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { debug } from "debug"
|
|
2
|
+
import nodeVault from "node-vault";
|
|
3
|
+
import { vaultRead } from "./vaultRead";
|
|
4
|
+
const dbg = debug('vaultFill')
|
|
5
|
+
|
|
6
|
+
export function vaultFill(vaultInstance: nodeVault.client, inputObject: any, ignoreError = false, keepCache = true) {
|
|
7
|
+
// v2.1
|
|
8
|
+
// fills all strings with ^vault@/secret/... with proper vault values
|
|
9
|
+
// if you call it again, it does reload the configuration
|
|
10
|
+
// v2.2
|
|
11
|
+
// supports keepCache - if vault fails, we will keep previous values instead of filling with false
|
|
12
|
+
return new Promise(async function (resolve, reject) {
|
|
13
|
+
let vaultKeys = Array<string>()
|
|
14
|
+
let vaultResults: any = {}
|
|
15
|
+
findVaultKeyMappings(inputObject, vaultKeys)
|
|
16
|
+
|
|
17
|
+
// read these keys from vault
|
|
18
|
+
for (let idx in vaultKeys) {
|
|
19
|
+
const val = vaultKeys[idx]
|
|
20
|
+
if (typeof val !== "string") continue
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
let got = await vaultRead(vaultInstance, vaultKeys[idx])
|
|
24
|
+
got['__vaultkey'] = val
|
|
25
|
+
got['__vaultfilled'] = Date.now()
|
|
26
|
+
vaultResults[val]=got
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
|
|
30
|
+
dbg(`Could not read vaultKey '${val}'`, err)
|
|
31
|
+
if (!ignoreError) vaultResults[val]=false
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fillVaultKeyMappings(inputObject, vaultResults, keepCache)
|
|
36
|
+
|
|
37
|
+
resolve(true)
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
function findVaultKeyMappings(config: any, keys = Array<string>()) {
|
|
43
|
+
for (var i in config) {
|
|
44
|
+
if (config[i] !== null) {
|
|
45
|
+
if (typeof config[i] === 'object' && (config[i].constructor.name === 'Array' || config[i].constructor.name === 'Object'))
|
|
46
|
+
findVaultKeyMappings(config[i], keys)
|
|
47
|
+
|
|
48
|
+
// detect previously read vaultKey
|
|
49
|
+
if (i === '__vaultkey') {
|
|
50
|
+
if (!keys.includes(vaultKey)) keys.push(config[i])
|
|
51
|
+
continue
|
|
52
|
+
}
|
|
53
|
+
// --
|
|
54
|
+
if (typeof config[i] === 'string' && config[i].search(/^vault@/) == 0) {
|
|
55
|
+
var splitted = config[i].split(/vault@/)
|
|
56
|
+
if (splitted.length == 2) {
|
|
57
|
+
var vaultKey = splitted[1]
|
|
58
|
+
if (!keys.includes(vaultKey)) keys.push(vaultKey)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function fillVaultKeyMappings(config: any, vaultResults:any, keepCache = true) {
|
|
66
|
+
for (var i in config) {
|
|
67
|
+
if (config[i] !== null) {
|
|
68
|
+
|
|
69
|
+
if (config[i] && config[i].constructor.name === 'Object' && config[i].hasOwnProperty('__vaultkey')) {
|
|
70
|
+
if (keepCache) {
|
|
71
|
+
if (vaultResults[config[i]['__vaultkey']]) config[i] = vaultResults[config[i]['__vaultkey']]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
else
|
|
75
|
+
config[i] = vaultResults[config[i]['__vaultkey']]
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
if (typeof config[i] === 'object' && (config[i].constructor.name === 'Array' || config[i].constructor.name === 'Object'))
|
|
79
|
+
fillVaultKeyMappings(config[i], vaultResults)
|
|
80
|
+
if (typeof config[i] === 'string' && config[i].search(/^vault@/) == 0) {
|
|
81
|
+
var splitted = config[i].split(/vault@/)
|
|
82
|
+
if (splitted.length == 2) {
|
|
83
|
+
var vaultKey = splitted[1]
|
|
84
|
+
config[i] = vaultResults[vaultKey]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.vaultRead = void 0;
|
|
7
|
+
const debug_1 = require("debug");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const fileCacheIsValid_1 = require("./fileCacheIsValid");
|
|
12
|
+
const global_1 = require("../global");
|
|
13
|
+
const hash_sha512_1 = require("./hash_sha512");
|
|
14
|
+
const dbg = (0, debug_1.debug)('vaultRead');
|
|
15
|
+
// need to implement it better
|
|
16
|
+
function vaultRead(vaultInstance, vaultKey, cache_in_minutes = 10) {
|
|
17
|
+
// v2 - supports caching
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
let cache_file = path_1.default.join(global_1.vault_cache_folder, (0, hash_sha512_1.hash_sha512)(`${vaultInstance.endpoint}/${vaultKey}`));
|
|
20
|
+
if (cache_in_minutes > 0 && (0, fileCacheIsValid_1.fileCacheIsValid)(cache_file, cache_in_minutes))
|
|
21
|
+
return resolve(JSON.parse((0, node_fs_1.readFileSync)(cache_file).toString()));
|
|
22
|
+
vaultInstance.read(vaultKey).then((r) => {
|
|
23
|
+
if (r.data) {
|
|
24
|
+
dbg(`vault ${vaultKey} - success`);
|
|
25
|
+
if (cache_in_minutes > 0)
|
|
26
|
+
try {
|
|
27
|
+
fs_1.default.writeFileSync(cache_file, JSON.stringify(r.data));
|
|
28
|
+
fs_1.default.chmodSync(cache_file, 0o600);
|
|
29
|
+
}
|
|
30
|
+
catch (_) { }
|
|
31
|
+
return resolve(r.data);
|
|
32
|
+
}
|
|
33
|
+
dbg(`vault ${vaultKey} - failed`);
|
|
34
|
+
reject(r);
|
|
35
|
+
}).catch(e => {
|
|
36
|
+
dbg(`exception inside vaultRead`, e);
|
|
37
|
+
// we will still return latest information from cache
|
|
38
|
+
try {
|
|
39
|
+
dbg(`returning vault@${vaultKey} from cache due to error`);
|
|
40
|
+
if (fs_1.default.existsSync(cache_file))
|
|
41
|
+
return resolve(JSON.parse(fs_1.default.readFileSync(cache_file).toString()));
|
|
42
|
+
}
|
|
43
|
+
catch (e2) {
|
|
44
|
+
// content of the file is invalid
|
|
45
|
+
console.log(e2);
|
|
46
|
+
}
|
|
47
|
+
reject(e);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
exports.vaultRead = vaultRead;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { debug } from "debug"
|
|
2
|
+
import nodeVault from "node-vault";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { fileCacheIsValid } from "./fileCacheIsValid";
|
|
7
|
+
import { vault_cache_folder } from "../global";
|
|
8
|
+
import { hash_sha512 } from "./hash_sha512";
|
|
9
|
+
const dbg = debug('vaultRead')
|
|
10
|
+
|
|
11
|
+
// need to implement it better
|
|
12
|
+
|
|
13
|
+
export function vaultRead(vaultInstance: nodeVault.client, vaultKey: string, cache_in_minutes = 10) : Promise<any> {
|
|
14
|
+
// v2 - supports caching
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
let cache_file = path.join(vault_cache_folder, hash_sha512(`${vaultInstance.endpoint}/${vaultKey}`))
|
|
17
|
+
|
|
18
|
+
if (cache_in_minutes > 0 && fileCacheIsValid(cache_file, cache_in_minutes))
|
|
19
|
+
return resolve(JSON.parse(readFileSync(cache_file as string).toString()))
|
|
20
|
+
|
|
21
|
+
vaultInstance.read(vaultKey).then((r) => {
|
|
22
|
+
if (r.data) {
|
|
23
|
+
dbg(`vault ${vaultKey} - success`)
|
|
24
|
+
if (cache_in_minutes > 0)
|
|
25
|
+
try { fs.writeFileSync(cache_file, JSON.stringify(r.data)); fs.chmodSync(cache_file, 0o600); } catch (_) { }
|
|
26
|
+
return resolve(r.data);
|
|
27
|
+
}
|
|
28
|
+
dbg(`vault ${vaultKey} - failed`)
|
|
29
|
+
reject(r);
|
|
30
|
+
}).catch(e => {
|
|
31
|
+
dbg(`exception inside vaultRead`, e)
|
|
32
|
+
// we will still return latest information from cache
|
|
33
|
+
try {
|
|
34
|
+
dbg(`returning vault@${vaultKey} from cache due to error`)
|
|
35
|
+
if (fs.existsSync(cache_file))
|
|
36
|
+
return resolve(JSON.parse(fs.readFileSync(cache_file as string).toString()))
|
|
37
|
+
} catch (e2) {
|
|
38
|
+
// content of the file is invalid
|
|
39
|
+
console.log(e2)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
reject(e);
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function wait(seconds?: number): Promise<void>;
|
package/ts/funcs/wait.js
ADDED
package/ts/funcs/wait.ts
ADDED
package/ts/global.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.vault_cache_folder = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
exports.vault_cache_folder = '/var/tmp/vault-cache';
|
|
9
|
+
try {
|
|
10
|
+
if (!fs_1.default.existsSync(exports.vault_cache_folder))
|
|
11
|
+
fs_1.default.mkdirSync(exports.vault_cache_folder);
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
console.log(e);
|
|
15
|
+
}
|
package/ts/global.ts
ADDED
package/ts/index.d.ts
CHANGED
package/ts/index.js
CHANGED
|
@@ -19,3 +19,8 @@ __exportStar(require("./funcs/isLocal"), exports);
|
|
|
19
19
|
__exportStar(require("./funcs/randomString"), exports);
|
|
20
20
|
__exportStar(require("./funcs/utcnow"), exports);
|
|
21
21
|
__exportStar(require("./funcs/validIp"), exports);
|
|
22
|
+
__exportStar(require("./funcs/wait"), exports);
|
|
23
|
+
__exportStar(require("./funcs/fileCacheIsValid"), exports);
|
|
24
|
+
__exportStar(require("./funcs/hash_sha512"), exports);
|
|
25
|
+
__exportStar(require("./funcs/vaultRead"), exports);
|
|
26
|
+
__exportStar(require("./funcs/vaultFill"), exports);
|
package/ts/index.test.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as IMPORTS from "./index";
|
|
2
2
|
|
|
3
3
|
test('exports', () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
expect(typeof IMPORTS.utcnow).toBe('function')
|
|
8
|
-
expect(typeof IMPORTS.validIp).toBe('function')
|
|
4
|
+
for(let fn of Object.values(IMPORTS)) {
|
|
5
|
+
expect(typeof fn).toBe('function')
|
|
6
|
+
}
|
|
9
7
|
})
|
package/ts/index.ts
CHANGED
|
@@ -3,4 +3,10 @@ export * from "./funcs/isLocal"
|
|
|
3
3
|
export * from "./funcs/randomString"
|
|
4
4
|
export * from "./funcs/utcnow"
|
|
5
5
|
export * from "./funcs/validIp"
|
|
6
|
-
|
|
6
|
+
export * from "./funcs/wait"
|
|
7
|
+
export * from "./funcs/fileCacheIsValid"
|
|
8
|
+
export * from "./funcs/hash_sha512"
|
|
9
|
+
export * from "./funcs/vaultRead"
|
|
10
|
+
export * from "./funcs/vaultFill"
|
|
11
|
+
export * from "./funcs/asJSON"
|
|
12
|
+
export * from "./funcs/promiseTimeout"
|