lemon-core 4.1.15 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/common/test-helper.d.ts +2 -2
- package/dist/common/test-helper.js +24 -26
- package/dist/common/test-helper.js.map +1 -1
- package/dist/controllers/dummy-controller.js +39 -46
- package/dist/controllers/dummy-controller.js.map +1 -1
- package/dist/controllers/general-api-controller.js +95 -100
- package/dist/controllers/general-api-controller.js.map +1 -1
- package/dist/controllers/general-controller.js +81 -82
- package/dist/controllers/general-controller.js.map +1 -1
- package/dist/cores/api/api-service.d.ts +1 -1
- package/dist/cores/api/api-service.js +228 -269
- package/dist/cores/api/api-service.js.map +1 -1
- package/dist/cores/aws/aws-kms-service.d.ts +1 -2
- package/dist/cores/aws/aws-kms-service.js +143 -153
- package/dist/cores/aws/aws-kms-service.js.map +1 -1
- package/dist/cores/aws/aws-s3-service.d.ts +2 -4
- package/dist/cores/aws/aws-s3-service.js +306 -330
- package/dist/cores/aws/aws-s3-service.js.map +1 -1
- package/dist/cores/aws/aws-sns-service.js +147 -153
- package/dist/cores/aws/aws-sns-service.js.map +1 -1
- package/dist/cores/aws/aws-sqs-service.js +149 -170
- package/dist/cores/aws/aws-sqs-service.js.map +1 -1
- package/dist/cores/aws/index.js +10 -20
- package/dist/cores/aws/index.js.map +1 -1
- package/dist/cores/cache/cache-service.d.ts +2 -2
- package/dist/cores/cache/cache-service.js +435 -499
- package/dist/cores/cache/cache-service.js.map +1 -1
- package/dist/cores/config/config-service.d.ts +1 -1
- package/dist/cores/config/config-service.js +56 -63
- package/dist/cores/config/config-service.js.map +1 -1
- package/dist/cores/config/index.js +14 -24
- package/dist/cores/config/index.js.map +1 -1
- package/dist/cores/core-services.d.ts +1 -1
- package/dist/cores/dynamo/dynamo-query-service.js +37 -51
- package/dist/cores/dynamo/dynamo-query-service.js.map +1 -1
- package/dist/cores/dynamo/dynamo-scan-service.d.ts +2 -2
- package/dist/cores/dynamo/dynamo-scan-service.js +29 -40
- package/dist/cores/dynamo/dynamo-scan-service.js.map +1 -1
- package/dist/cores/dynamo/dynamo-service.d.ts +3 -3
- package/dist/cores/dynamo/dynamo-service.js +540 -605
- package/dist/cores/dynamo/dynamo-service.js.map +1 -1
- package/dist/cores/dynamo/tools/expressions.js +17 -7
- package/dist/cores/dynamo/tools/expressions.js.map +1 -1
- package/dist/cores/dynamo/tools/query.js +142 -127
- package/dist/cores/dynamo/tools/query.js.map +1 -1
- package/dist/cores/dynamo/tools/scan.js +111 -97
- package/dist/cores/dynamo/tools/scan.js.map +1 -1
- package/dist/cores/dynamo/tools/serializer.js +17 -7
- package/dist/cores/dynamo/tools/serializer.js.map +1 -1
- package/dist/cores/dynamo/tools/utils.d.ts +0 -2
- package/dist/cores/dynamo/tools/utils.js.map +1 -1
- package/dist/cores/elastic/elastic6-query-service.js +307 -324
- package/dist/cores/elastic/elastic6-query-service.js.map +1 -1
- package/dist/cores/elastic/elastic6-service.d.ts +3 -3
- package/dist/cores/elastic/elastic6-service.js +568 -647
- package/dist/cores/elastic/elastic6-service.js.map +1 -1
- package/dist/cores/elastic/hangul-service.js +52 -54
- package/dist/cores/elastic/hangul-service.js.map +1 -1
- package/dist/cores/lambda/index.js +42 -36
- package/dist/cores/lambda/index.js.map +1 -1
- package/dist/cores/lambda/lambda-alb-handler.d.ts +2 -2
- package/dist/cores/lambda/lambda-alb-handler.js +59 -72
- package/dist/cores/lambda/lambda-alb-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-cognito-handler.js +10 -19
- package/dist/cores/lambda/lambda-cognito-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-cron-handler.d.ts +1 -1
- package/dist/cores/lambda/lambda-cron-handler.js +14 -23
- package/dist/cores/lambda/lambda-cron-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-dynamo-stream-handler.d.ts +2 -2
- package/dist/cores/lambda/lambda-dynamo-stream-handler.js +57 -67
- package/dist/cores/lambda/lambda-dynamo-stream-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-handler.d.ts +22 -22
- package/dist/cores/lambda/lambda-handler.js +93 -106
- package/dist/cores/lambda/lambda-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-notification-handler.d.ts +1 -1
- package/dist/cores/lambda/lambda-notification-handler.js +39 -50
- package/dist/cores/lambda/lambda-notification-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-sns-handler.js +79 -88
- package/dist/cores/lambda/lambda-sns-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-sqs-handler.js +79 -88
- package/dist/cores/lambda/lambda-sqs-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-web-handler.d.ts +6 -6
- package/dist/cores/lambda/lambda-web-handler.js +387 -412
- package/dist/cores/lambda/lambda-web-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-wss-handler.js +23 -32
- package/dist/cores/lambda/lambda-wss-handler.js.map +1 -1
- package/dist/cores/protocol/index.js +10 -20
- package/dist/cores/protocol/index.js.map +1 -1
- package/dist/cores/protocol/protocol-service.d.ts +3 -3
- package/dist/cores/protocol/protocol-service.js +235 -227
- package/dist/cores/protocol/protocol-service.js.map +1 -1
- package/dist/cores/storage/http-storage-service.js +65 -85
- package/dist/cores/storage/http-storage-service.js.map +1 -1
- package/dist/cores/storage/model-manager.js +66 -85
- package/dist/cores/storage/model-manager.js.map +1 -1
- package/dist/cores/storage/proxy-storage-service.d.ts +2 -2
- package/dist/cores/storage/proxy-storage-service.js +562 -599
- package/dist/cores/storage/proxy-storage-service.js.map +1 -1
- package/dist/cores/storage/redis-storage-service.js +163 -177
- package/dist/cores/storage/redis-storage-service.js.map +1 -1
- package/dist/cores/storage/storage-service.d.ts +8 -1
- package/dist/cores/storage/storage-service.js +359 -324
- package/dist/cores/storage/storage-service.js.map +1 -1
- package/dist/engine/builder.d.ts +1 -1
- package/dist/engine/builder.js +59 -63
- package/dist/engine/builder.js.map +1 -1
- package/dist/engine/engine.d.ts +4 -4
- package/dist/engine/engine.js +9 -18
- package/dist/engine/engine.js.map +1 -1
- package/dist/engine/types.d.ts +1 -1
- package/dist/engine/utilities.d.ts +5 -5
- package/dist/engine/utilities.js +301 -293
- package/dist/engine/utilities.js.map +1 -1
- package/dist/environ.js +4 -6
- package/dist/environ.js.map +1 -1
- package/dist/extended/abstract-service.js +595 -645
- package/dist/extended/abstract-service.js.map +1 -1
- package/dist/extended/libs/sig-v4.js.map +1 -1
- package/dist/generated/field-registry.d.ts +10 -0
- package/dist/generated/field-registry.js +17 -0
- package/dist/generated/field-registry.js.map +1 -0
- package/dist/helpers/helpers.d.ts +17 -9
- package/dist/helpers/helpers.js +88 -78
- package/dist/helpers/helpers.js.map +1 -1
- package/dist/index.js +17 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/dynamodb-value.js +2 -3
- package/dist/lib/dynamodb-value.js.map +1 -1
- package/dist/tools/express.js +4 -5
- package/dist/tools/express.js.map +1 -1
- package/dist/tools/tools.d.ts +3 -1
- package/dist/tools/tools.js +14 -21
- package/dist/tools/tools.js.map +1 -1
- package/package.json +25 -24
- package/dist/exec-cli.d.ts +0 -2
- package/dist/exec-cli.js +0 -211
- package/dist/exec-cli.js.map +0 -1
- package/dist/lib/dynamo/expressions.d.ts +0 -14
- package/dist/lib/dynamo/expressions.js +0 -212
- package/dist/lib/dynamo/expressions.js.map +0 -1
- package/dist/lib/dynamo/query.d.ts +0 -43
- package/dist/lib/dynamo/query.js +0 -246
- package/dist/lib/dynamo/query.js.map +0 -1
- package/dist/lib/dynamo/scan.d.ts +0 -33
- package/dist/lib/dynamo/scan.js +0 -172
- package/dist/lib/dynamo/scan.js.map +0 -1
- package/dist/lib/dynamo/serializer.d.ts +0 -12
- package/dist/lib/dynamo/serializer.js +0 -243
- package/dist/lib/dynamo/serializer.js.map +0 -1
- package/dist/lib/dynamo/utils.d.ts +0 -15
- package/dist/lib/dynamo/utils.js +0 -129
- package/dist/lib/dynamo/utils.js.map +0 -1
- package/dist/tools/shared.d.ts +0 -28
- package/dist/tools/shared.js +0 -143
- package/dist/tools/shared.js.map +0 -1
package/dist/engine/utilities.js
CHANGED
|
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
37
|
};
|
|
@@ -49,291 +59,11 @@ const COLORS = {
|
|
|
49
59
|
* - various functions
|
|
50
60
|
*/
|
|
51
61
|
class Utilities {
|
|
62
|
+
_$;
|
|
63
|
+
log;
|
|
64
|
+
err;
|
|
65
|
+
name;
|
|
52
66
|
constructor(_$) {
|
|
53
|
-
/**
|
|
54
|
-
* parse float by decimal point 2
|
|
55
|
-
*/
|
|
56
|
-
this.F2 = (x, mode = 'round') => this.FN(x, 2, mode);
|
|
57
|
-
/**
|
|
58
|
-
* parse float by decimal point 3
|
|
59
|
-
*/
|
|
60
|
-
this.F3 = (x, mode = 'round') => this.FN(x, 3, mode);
|
|
61
|
-
/**
|
|
62
|
-
* convert and cut string like `abcd....z`
|
|
63
|
-
*/
|
|
64
|
-
this.S = (_, h, t = 32, delim = '...') => [typeof _ == 'string' ? _ : `${this.json(_) || ''}`]
|
|
65
|
-
.map(s => h && s.length > h + t
|
|
66
|
-
? s.substring(0, h) + delim + (s.length > h + t ? s.substring(s.length - t) : '')
|
|
67
|
-
: s)
|
|
68
|
-
.join('');
|
|
69
|
-
/**
|
|
70
|
-
* group as qs
|
|
71
|
-
*/
|
|
72
|
-
this.qs = {
|
|
73
|
-
/**
|
|
74
|
-
* parse qs string
|
|
75
|
-
*/
|
|
76
|
-
parse: (q) => this.qs_parse(q),
|
|
77
|
-
/**
|
|
78
|
-
* stringify qs object
|
|
79
|
-
*/
|
|
80
|
-
stringify: (q) => this.qs_stringify(q),
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* get crypto object.
|
|
84
|
-
*
|
|
85
|
-
* @deprecated since nodejs22, use `crypto2` instead.
|
|
86
|
-
*/
|
|
87
|
-
this.crypto = (passwd, algorithm) => {
|
|
88
|
-
algorithm = algorithm || 'aes-256-ctr';
|
|
89
|
-
const MAGIC = 'LM!#';
|
|
90
|
-
/**
|
|
91
|
-
* Simulate OpenSSL's EVP_BytesToKey method
|
|
92
|
-
*/
|
|
93
|
-
const evpBytesToKey = (password, keyLen, ivLen) => {
|
|
94
|
-
let data = Buffer.alloc(0);
|
|
95
|
-
let prev = Buffer.alloc(0);
|
|
96
|
-
while (data.length < keyLen + ivLen) {
|
|
97
|
-
const hash = crypto_1.default.createHash('md5');
|
|
98
|
-
hash.update(Buffer.concat([prev, password]));
|
|
99
|
-
prev = hash.digest();
|
|
100
|
-
data = Buffer.concat([data, prev]);
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
key: data.slice(0, keyLen),
|
|
104
|
-
iv: data.slice(keyLen, keyLen + ivLen),
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
const getKeyIV = () => {
|
|
108
|
-
const passwordBuf = Buffer.from(passwd, 'binary');
|
|
109
|
-
const keyLen = 32; // for aes-256
|
|
110
|
-
const ivLen = 16; // AES block size
|
|
111
|
-
return evpBytesToKey(passwordBuf, keyLen, ivLen);
|
|
112
|
-
};
|
|
113
|
-
return new (class {
|
|
114
|
-
constructor() {
|
|
115
|
-
/** @deprecated since nodejs22 */
|
|
116
|
-
this.encrypt = (val) => {
|
|
117
|
-
val = val === undefined ? null : val;
|
|
118
|
-
// msg = msg && typeof msg == 'object' ? JSON_TAG+JSON.stringify(msg) : msg;
|
|
119
|
-
//* 어느 데이터 타입이든 저장하기 위해서, object로 만든다음, 암호화 시킨다.
|
|
120
|
-
const msg = JSON.stringify({ alg: algorithm, val: val });
|
|
121
|
-
const buffer = Buffer.from(`${MAGIC}${msg || ''}`, 'utf8');
|
|
122
|
-
const { key, iv } = getKeyIV();
|
|
123
|
-
const cipher = crypto_1.default.createCipheriv(algorithm, key, iv);
|
|
124
|
-
const crypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
|
|
125
|
-
return crypted.toString(1 ? 'base64' : 'utf8');
|
|
126
|
-
};
|
|
127
|
-
/** @deprecated since nodejs22 */
|
|
128
|
-
this.decrypt = (msg) => {
|
|
129
|
-
const buffer = Buffer.from(`${msg || ''}`, 'base64');
|
|
130
|
-
const { key, iv } = getKeyIV();
|
|
131
|
-
const decipher = crypto_1.default.createDecipheriv(algorithm, key, iv);
|
|
132
|
-
const decrypted = Buffer.concat([decipher.update(buffer), decipher.final()]);
|
|
133
|
-
const dec = decrypted.toString('utf8');
|
|
134
|
-
if (!dec.startsWith(MAGIC))
|
|
135
|
-
throw new Error('400 INVALID PASSWD - invalid magic string!');
|
|
136
|
-
const data = dec.slice(MAGIC.length);
|
|
137
|
-
if (data && !data.startsWith('{') && !data.endsWith('}'))
|
|
138
|
-
throw new Error('400 INVALID PASSWD - invalid json string!');
|
|
139
|
-
const $msg = JSON.parse(data) || {};
|
|
140
|
-
return $msg.val;
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
})();
|
|
144
|
-
};
|
|
145
|
-
/**
|
|
146
|
-
* get crypto2 object (w/ Cipheriv).
|
|
147
|
-
* - to avoid `(node:66818) Warning: Use Cipheriv for counter mode of aes-256-ctr`
|
|
148
|
-
*
|
|
149
|
-
* @param passwd password to crypt
|
|
150
|
-
* @param algorithm (default as `aes-256-ctr`)
|
|
151
|
-
* @param ivNumb iv number to populate. (default as 0, or -1 use random)
|
|
152
|
-
* @param magic magic string to verify (default `LM!#`)
|
|
153
|
-
*/
|
|
154
|
-
this.crypto2 = (passwd, algorithm, ivNumb, magic) => {
|
|
155
|
-
algorithm = algorithm || 'aes-256-ctr';
|
|
156
|
-
const MAGIC = magic === undefined ? 'LM!#' : `${magic || ''}`;
|
|
157
|
-
const iv = Buffer.from(Array.prototype.map.call(Buffer.alloc(16), () => {
|
|
158
|
-
return ivNumb === undefined ? 0 : ivNumb === -1 ? Math.floor(Math.random() * 256) : ivNumb;
|
|
159
|
-
}));
|
|
160
|
-
return new (class {
|
|
161
|
-
constructor() {
|
|
162
|
-
this.encrypt = (val) => {
|
|
163
|
-
val = val === undefined ? null : val;
|
|
164
|
-
//* use json string to support all data-type
|
|
165
|
-
const msg = JSON.stringify({ alg: algorithm, val: val });
|
|
166
|
-
const buffer = Buffer.from(`${MAGIC}${msg || ''}`, 'utf8');
|
|
167
|
-
const key = Buffer.concat([Buffer.from(passwd)], Buffer.alloc(32).length);
|
|
168
|
-
const cipher = crypto_1.default.createCipheriv(algorithm, key, iv);
|
|
169
|
-
const crypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
|
|
170
|
-
return crypted.toString('base64');
|
|
171
|
-
};
|
|
172
|
-
this.decrypt = (msg) => {
|
|
173
|
-
const buffer = Buffer.from(`${msg || ''}`, 'base64');
|
|
174
|
-
const key = Buffer.concat([Buffer.from(passwd)], Buffer.alloc(32).length);
|
|
175
|
-
const decipher = crypto_1.default.createDecipheriv(algorithm, key, iv);
|
|
176
|
-
const dec = Buffer.concat([decipher.update(buffer), decipher.final()]).toString('utf8');
|
|
177
|
-
if (!dec.startsWith(MAGIC))
|
|
178
|
-
throw new Error(`400 INVALID PASSWD - invalid magic string!`);
|
|
179
|
-
const data = dec.substr(MAGIC.length);
|
|
180
|
-
if (data && !data.startsWith('{') && !data.endsWith('}'))
|
|
181
|
-
throw new Error('400 INVALID PASSWD - invalid json string!');
|
|
182
|
-
const $msg = JSON.parse(data) || {};
|
|
183
|
-
return $msg.val;
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
})();
|
|
187
|
-
};
|
|
188
|
-
/**
|
|
189
|
-
* get crypto3 object (with nonce + timestamp based IV).
|
|
190
|
-
*
|
|
191
|
-
* format details, see `crypto3` tests.
|
|
192
|
-
* 1. nonce = random hex string with length 13 (like `a1b2c3d4e5f67`)
|
|
193
|
-
* 2. head = `LM!#${VERSION}:${nonce}:${timestamp}` -> base64 encode with constant length 48 (no padding)
|
|
194
|
-
* 3. body = JSON({d: data}) -> encrypted by AES-256-CTR with key = passwd
|
|
195
|
-
* 4. final = [head, body].join('')
|
|
196
|
-
*
|
|
197
|
-
* @param passwd password to crypt
|
|
198
|
-
* @param algorithm (default as `aes-256-ctr`)
|
|
199
|
-
*/
|
|
200
|
-
this.crypto3 = (passwd, algorithm) => {
|
|
201
|
-
algorithm = algorithm || 'aes-256-ctr';
|
|
202
|
-
const MAGIC = 'LM!#';
|
|
203
|
-
const VERSION = 'V003';
|
|
204
|
-
const HEAD_B64_LEN = 48; // 36 bytes -> 48 base64 (no padding)
|
|
205
|
-
const errScope = `crypto3(${algorithm}#${VERSION})`;
|
|
206
|
-
const key = Buffer.concat([Buffer.from(passwd)], Buffer.alloc(32).length);
|
|
207
|
-
const hmac = (data, sig) => this.hmac(data, sig, 'sha256', 'hex');
|
|
208
|
-
const currentMs = () => this.current_time_ms(); // 13 digits timestamp
|
|
209
|
-
const makeNonce = () => this.uuid().replace(/-/g, '').substring(0, 13); // 13 chars (52-bit entropy)
|
|
210
|
-
return new (class {
|
|
211
|
-
constructor() {
|
|
212
|
-
this.encrypt = (val, options) => {
|
|
213
|
-
var _a, _b;
|
|
214
|
-
val = val === undefined ? null : val;
|
|
215
|
-
const nonce = (_a = options === null || options === void 0 ? void 0 : options.nonce) !== null && _a !== void 0 ? _a : makeNonce();
|
|
216
|
-
const timestamp = String((_b = options === null || options === void 0 ? void 0 : options.current) !== null && _b !== void 0 ? _b : currentMs()).padStart(13, '0');
|
|
217
|
-
const iv = Buffer.from(hmac(`${nonce}:${timestamp}`, passwd).substring(0, 32), 'hex'); // AES IV must be 16 bytes.
|
|
218
|
-
const buffer = Buffer.from(JSON.stringify({ d: val }), 'utf8');
|
|
219
|
-
const cipher = crypto_1.default.createCipheriv(algorithm, key, iv);
|
|
220
|
-
const crypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
|
|
221
|
-
const headRaw = `${MAGIC}${VERSION}:${nonce}:${timestamp}`;
|
|
222
|
-
const head = Buffer.from(headRaw).toString('base64');
|
|
223
|
-
const body = crypted.toString('base64');
|
|
224
|
-
return [head, body].join('');
|
|
225
|
-
};
|
|
226
|
-
this.decrypt = (msg, options) => {
|
|
227
|
-
var _a;
|
|
228
|
-
if (!msg)
|
|
229
|
-
throw new Error(`@msg (string) is required - ${errScope}`);
|
|
230
|
-
if (msg.length < HEAD_B64_LEN)
|
|
231
|
-
throw new Error(`400 INVALID DATA - data too short! @${errScope}`);
|
|
232
|
-
// 1. decode base64 header (48 chars -> 36 bytes)
|
|
233
|
-
const headBase64 = msg.substring(0, HEAD_B64_LEN);
|
|
234
|
-
const head = Buffer.from(headBase64, 'base64').toString('utf8');
|
|
235
|
-
if (head.length !== 36)
|
|
236
|
-
throw new Error(`400 INVALID DATA - invalid header! @${errScope}`);
|
|
237
|
-
// 2. validate magic and version
|
|
238
|
-
if (!head.startsWith(MAGIC))
|
|
239
|
-
throw new Error(`400 INVALID MAGIC - invalid magic! @${errScope}`);
|
|
240
|
-
const version = head.substring(4, 8);
|
|
241
|
-
if (version !== VERSION)
|
|
242
|
-
throw new Error(`400 INVALID VERSION - expected ${VERSION}, got ${version}! @${errScope}`);
|
|
243
|
-
// 3. parse nonce, timestamp (format: LM!#V003:nonce:timestamp)
|
|
244
|
-
const [, nonce, timestamp] = head.substring(8).split(':');
|
|
245
|
-
if (!nonce || nonce.length !== 13)
|
|
246
|
-
throw new Error(`400 INVALID DATA - invalid nonce! @${errScope}`);
|
|
247
|
-
if (!timestamp || !/^\d+$/.test(timestamp))
|
|
248
|
-
throw new Error(`400 INVALID DATA - invalid timestamp! @${errScope}`);
|
|
249
|
-
if ((options === null || options === void 0 ? void 0 : options.maxAge) !== undefined) {
|
|
250
|
-
const current = (_a = options === null || options === void 0 ? void 0 : options.current) !== null && _a !== void 0 ? _a : currentMs();
|
|
251
|
-
if (current - parseInt(timestamp, 10) > options.maxAge)
|
|
252
|
-
throw new Error(`400 INVALID DATA - expired timestamp! @${errScope}`);
|
|
253
|
-
}
|
|
254
|
-
// 4. decrypt
|
|
255
|
-
const iv = Buffer.from(hmac(`${nonce}:${timestamp}`, passwd).substring(0, 32), 'hex');
|
|
256
|
-
const decipher = crypto_1.default.createDecipheriv(algorithm, key, iv);
|
|
257
|
-
const dec = Buffer.concat([
|
|
258
|
-
decipher.update(Buffer.from(msg.substring(HEAD_B64_LEN), 'base64')),
|
|
259
|
-
decipher.final(),
|
|
260
|
-
]).toString('utf8');
|
|
261
|
-
if (!dec.startsWith('{') || !dec.endsWith('}'))
|
|
262
|
-
throw new Error(`400 INVALID PASSWD - invalid json string @${errScope}`);
|
|
263
|
-
const $msg = JSON.parse(dec) || {};
|
|
264
|
-
return $msg === null || $msg === void 0 ? void 0 : $msg.d;
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
})();
|
|
268
|
-
};
|
|
269
|
-
/**
|
|
270
|
-
* encrypt shorthand using crypto3
|
|
271
|
-
*/
|
|
272
|
-
this.encrypt = (data, secret, options) => {
|
|
273
|
-
return this.crypto3(secret).encrypt(data, options);
|
|
274
|
-
};
|
|
275
|
-
/**
|
|
276
|
-
* decrypt shorthand using crypto3
|
|
277
|
-
*/
|
|
278
|
-
this.decrypt = (data, secret, options) => {
|
|
279
|
-
return this.crypto3(secret).decrypt(data, options);
|
|
280
|
-
};
|
|
281
|
-
/**
|
|
282
|
-
* builder for `JWTHelper`
|
|
283
|
-
* @param passcode string for verification.
|
|
284
|
-
* @param current_ms (optional) current time in millisecond (required to verify `exp`)
|
|
285
|
-
*/
|
|
286
|
-
this.jwt = (passcode, current_ms) => {
|
|
287
|
-
const $U = this;
|
|
288
|
-
/**
|
|
289
|
-
* main class.
|
|
290
|
-
*/
|
|
291
|
-
return new (class JWTHelper {
|
|
292
|
-
constructor() {
|
|
293
|
-
/**
|
|
294
|
-
* use `jsonwebtoken` directly.
|
|
295
|
-
*/
|
|
296
|
-
this.$ = jsonwebtoken_1.default;
|
|
297
|
-
/**
|
|
298
|
-
* encode object to token string
|
|
299
|
-
* - Synchronous Sign with default (HS256: HMAC SHA256)
|
|
300
|
-
*
|
|
301
|
-
* @param data object
|
|
302
|
-
* @param algorithm algorithm to use
|
|
303
|
-
*/
|
|
304
|
-
this.encode = (data, algorithm = 'HS256') => {
|
|
305
|
-
data = current_ms ? Object.assign(Object.assign({}, data), { iat: Math.floor(current_ms / 1000) }) : data;
|
|
306
|
-
const token = jsonwebtoken_1.default.sign(data, passcode, { algorithm });
|
|
307
|
-
return token;
|
|
308
|
-
};
|
|
309
|
-
/**
|
|
310
|
-
* decode token string
|
|
311
|
-
*
|
|
312
|
-
* @param token string
|
|
313
|
-
*/
|
|
314
|
-
this.decode = (token, options) => {
|
|
315
|
-
const N = jsonwebtoken_1.default.decode(token, options);
|
|
316
|
-
return N;
|
|
317
|
-
};
|
|
318
|
-
/**
|
|
319
|
-
* verify token
|
|
320
|
-
* - Synchronous Verify with default (HS256: HMAC SHA256)
|
|
321
|
-
*
|
|
322
|
-
* @param token
|
|
323
|
-
* @param algorithm
|
|
324
|
-
* @throws `jwt expired` if exp has expired!.
|
|
325
|
-
*/
|
|
326
|
-
this.verify = (token, algorithm = 'HS256') => {
|
|
327
|
-
const verified = jsonwebtoken_1.default.verify(token, passcode, { algorithms: [algorithm] });
|
|
328
|
-
const cur = $U.N(current_ms, 0);
|
|
329
|
-
const exp = $U.N(verified === null || verified === void 0 ? void 0 : verified.exp, 0) * 1000;
|
|
330
|
-
if (cur > 0 && exp > 0 && exp < current_ms)
|
|
331
|
-
throw new Error(`jwt expired at ${$U.ts(exp)}`);
|
|
332
|
-
return verified;
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
})();
|
|
336
|
-
};
|
|
337
67
|
this._$ = _$;
|
|
338
68
|
this.log = _$.log;
|
|
339
69
|
this.err = _$.err;
|
|
@@ -651,6 +381,22 @@ class Utilities {
|
|
|
651
381
|
const val3 = val2 / div;
|
|
652
382
|
return val3;
|
|
653
383
|
}
|
|
384
|
+
/**
|
|
385
|
+
* parse float by decimal point 2
|
|
386
|
+
*/
|
|
387
|
+
F2 = (x, mode = 'round') => this.FN(x, 2, mode);
|
|
388
|
+
/**
|
|
389
|
+
* parse float by decimal point 3
|
|
390
|
+
*/
|
|
391
|
+
F3 = (x, mode = 'round') => this.FN(x, 3, mode);
|
|
392
|
+
/**
|
|
393
|
+
* convert and cut string like `abcd....z`
|
|
394
|
+
*/
|
|
395
|
+
S = (_, h, t = 32, delim = '...') => [typeof _ == 'string' ? _ : `${this.json(_) || ''}`]
|
|
396
|
+
.map(s => h && s.length > h + t
|
|
397
|
+
? s.substring(0, h) + delim + (s.length > h + t ? s.substring(s.length - t) : '')
|
|
398
|
+
: s)
|
|
399
|
+
.join('');
|
|
654
400
|
/**
|
|
655
401
|
* remove internal properties which starts with _ or $
|
|
656
402
|
*/
|
|
@@ -727,6 +473,7 @@ class Utilities {
|
|
|
727
473
|
*/
|
|
728
474
|
isEqual(obj1, obj2) {
|
|
729
475
|
const keys = Object.keys;
|
|
476
|
+
const toString = Object.prototype.toString;
|
|
730
477
|
function tagTester(name) {
|
|
731
478
|
return function (obj) {
|
|
732
479
|
return toString.call(obj) === '[object ' + name + ']';
|
|
@@ -919,7 +666,8 @@ class Utilities {
|
|
|
919
666
|
*/
|
|
920
667
|
md5(data, digest) {
|
|
921
668
|
digest = digest === undefined ? 'hex' : digest;
|
|
922
|
-
|
|
669
|
+
const _digest = digest === 'latin1' ? 'binary' : digest;
|
|
670
|
+
return crypto_1.default.createHash('md5').update(data).digest(_digest);
|
|
923
671
|
}
|
|
924
672
|
/**
|
|
925
673
|
* get hmac hash
|
|
@@ -928,7 +676,8 @@ class Utilities {
|
|
|
928
676
|
KEY = KEY || 'XENI';
|
|
929
677
|
encoding = encoding || 'base64';
|
|
930
678
|
algorithm = algorithm || 'sha256';
|
|
931
|
-
|
|
679
|
+
const _encoding = encoding === 'latin1' ? 'binary' : encoding;
|
|
680
|
+
return crypto_1.default.createHmac(algorithm, KEY).update(data).digest(_encoding);
|
|
932
681
|
}
|
|
933
682
|
/**
|
|
934
683
|
* parse query-string.
|
|
@@ -959,6 +708,265 @@ class Utilities {
|
|
|
959
708
|
const param = query_string_1.default.stringify(query);
|
|
960
709
|
return param;
|
|
961
710
|
}
|
|
711
|
+
/**
|
|
712
|
+
* group as qs
|
|
713
|
+
*/
|
|
714
|
+
qs = {
|
|
715
|
+
/**
|
|
716
|
+
* parse qs string
|
|
717
|
+
*/
|
|
718
|
+
parse: (q) => this.qs_parse(q),
|
|
719
|
+
/**
|
|
720
|
+
* stringify qs object
|
|
721
|
+
*/
|
|
722
|
+
stringify: (q) => this.qs_stringify(q),
|
|
723
|
+
};
|
|
724
|
+
/**
|
|
725
|
+
* get crypto object.
|
|
726
|
+
*
|
|
727
|
+
* @deprecated since nodejs22, use `crypto2` instead.
|
|
728
|
+
*/
|
|
729
|
+
crypto = (passwd, algorithm) => {
|
|
730
|
+
algorithm = algorithm || 'aes-256-ctr';
|
|
731
|
+
const MAGIC = 'LM!#';
|
|
732
|
+
/**
|
|
733
|
+
* Simulate OpenSSL's EVP_BytesToKey method
|
|
734
|
+
*/
|
|
735
|
+
const evpBytesToKey = (password, keyLen, ivLen) => {
|
|
736
|
+
let data = Buffer.alloc(0);
|
|
737
|
+
let prev = Buffer.alloc(0);
|
|
738
|
+
while (data.length < keyLen + ivLen) {
|
|
739
|
+
const hash = crypto_1.default.createHash('md5');
|
|
740
|
+
hash.update(Buffer.concat([prev, password]));
|
|
741
|
+
prev = hash.digest();
|
|
742
|
+
data = Buffer.concat([data, prev]);
|
|
743
|
+
}
|
|
744
|
+
return {
|
|
745
|
+
key: data.slice(0, keyLen),
|
|
746
|
+
iv: data.slice(keyLen, keyLen + ivLen),
|
|
747
|
+
};
|
|
748
|
+
};
|
|
749
|
+
const getKeyIV = () => {
|
|
750
|
+
const passwordBuf = Buffer.from(passwd, 'binary');
|
|
751
|
+
const keyLen = 32; // for aes-256
|
|
752
|
+
const ivLen = 16; // AES block size
|
|
753
|
+
return evpBytesToKey(passwordBuf, keyLen, ivLen);
|
|
754
|
+
};
|
|
755
|
+
return new (class {
|
|
756
|
+
/** @deprecated since nodejs22 */
|
|
757
|
+
encrypt = (val) => {
|
|
758
|
+
val = val === undefined ? null : val;
|
|
759
|
+
// msg = msg && typeof msg == 'object' ? JSON_TAG+JSON.stringify(msg) : msg;
|
|
760
|
+
//* 어느 데이터 타입이든 저장하기 위해서, object로 만든다음, 암호화 시킨다.
|
|
761
|
+
const msg = JSON.stringify({ alg: algorithm, val: val });
|
|
762
|
+
const buffer = Buffer.from(`${MAGIC}${msg || ''}`, 'utf8');
|
|
763
|
+
const { key, iv } = getKeyIV();
|
|
764
|
+
const cipher = crypto_1.default.createCipheriv(algorithm, key, iv);
|
|
765
|
+
const crypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
|
|
766
|
+
return crypted.toString(1 ? 'base64' : 'utf8');
|
|
767
|
+
};
|
|
768
|
+
/** @deprecated since nodejs22 */
|
|
769
|
+
decrypt = (msg) => {
|
|
770
|
+
const buffer = Buffer.from(`${msg || ''}`, 'base64');
|
|
771
|
+
const { key, iv } = getKeyIV();
|
|
772
|
+
const decipher = crypto_1.default.createDecipheriv(algorithm, key, iv);
|
|
773
|
+
const decrypted = Buffer.concat([decipher.update(buffer), decipher.final()]);
|
|
774
|
+
const dec = decrypted.toString('utf8');
|
|
775
|
+
if (!dec.startsWith(MAGIC))
|
|
776
|
+
throw new Error('400 INVALID PASSWD - invalid magic string!');
|
|
777
|
+
const data = dec.slice(MAGIC.length);
|
|
778
|
+
if (data && !data.startsWith('{') && !data.endsWith('}'))
|
|
779
|
+
throw new Error('400 INVALID PASSWD - invalid json string!');
|
|
780
|
+
const $msg = JSON.parse(data) || {};
|
|
781
|
+
return $msg.val;
|
|
782
|
+
};
|
|
783
|
+
})();
|
|
784
|
+
};
|
|
785
|
+
/**
|
|
786
|
+
* get crypto2 object (w/ Cipheriv).
|
|
787
|
+
* - to avoid `(node:66818) Warning: Use Cipheriv for counter mode of aes-256-ctr`
|
|
788
|
+
*
|
|
789
|
+
* @param passwd password to crypt
|
|
790
|
+
* @param algorithm (default as `aes-256-ctr`)
|
|
791
|
+
* @param ivNumb iv number to populate. (default as 0, or -1 use random)
|
|
792
|
+
* @param magic magic string to verify (default `LM!#`)
|
|
793
|
+
*/
|
|
794
|
+
crypto2 = (passwd, algorithm, ivNumb, magic) => {
|
|
795
|
+
algorithm = algorithm || 'aes-256-ctr';
|
|
796
|
+
const MAGIC = magic === undefined ? 'LM!#' : `${magic || ''}`;
|
|
797
|
+
const iv = Buffer.from(Array.prototype.map.call(Buffer.alloc(16), () => {
|
|
798
|
+
return ivNumb === undefined ? 0 : ivNumb === -1 ? Math.floor(Math.random() * 256) : ivNumb;
|
|
799
|
+
}));
|
|
800
|
+
return new (class {
|
|
801
|
+
encrypt = (val) => {
|
|
802
|
+
val = val === undefined ? null : val;
|
|
803
|
+
//* use json string to support all data-type
|
|
804
|
+
const msg = JSON.stringify({ alg: algorithm, val: val });
|
|
805
|
+
const buffer = Buffer.from(`${MAGIC}${msg || ''}`, 'utf8');
|
|
806
|
+
const key = Buffer.concat([Buffer.from(passwd)], Buffer.alloc(32).length);
|
|
807
|
+
const cipher = crypto_1.default.createCipheriv(algorithm, key, iv);
|
|
808
|
+
const crypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
|
|
809
|
+
return crypted.toString('base64');
|
|
810
|
+
};
|
|
811
|
+
decrypt = (msg) => {
|
|
812
|
+
const buffer = Buffer.from(`${msg || ''}`, 'base64');
|
|
813
|
+
const key = Buffer.concat([Buffer.from(passwd)], Buffer.alloc(32).length);
|
|
814
|
+
const decipher = crypto_1.default.createDecipheriv(algorithm, key, iv);
|
|
815
|
+
const dec = Buffer.concat([decipher.update(buffer), decipher.final()]).toString('utf8');
|
|
816
|
+
if (!dec.startsWith(MAGIC))
|
|
817
|
+
throw new Error(`400 INVALID PASSWD - invalid magic string!`);
|
|
818
|
+
const data = dec.substr(MAGIC.length);
|
|
819
|
+
if (data && !data.startsWith('{') && !data.endsWith('}'))
|
|
820
|
+
throw new Error('400 INVALID PASSWD - invalid json string!');
|
|
821
|
+
const $msg = JSON.parse(data) || {};
|
|
822
|
+
return $msg.val;
|
|
823
|
+
};
|
|
824
|
+
})();
|
|
825
|
+
};
|
|
826
|
+
/**
|
|
827
|
+
* get crypto3 object (with nonce + timestamp based IV).
|
|
828
|
+
*
|
|
829
|
+
* format details, see `crypto3` tests.
|
|
830
|
+
* 1. nonce = random hex string with length 13 (like `a1b2c3d4e5f67`)
|
|
831
|
+
* 2. head = `LM!#${VERSION}:${nonce}:${timestamp}` -> base64 encode with constant length 48 (no padding)
|
|
832
|
+
* 3. body = JSON({d: data}) -> encrypted by AES-256-CTR with key = passwd
|
|
833
|
+
* 4. final = [head, body].join('')
|
|
834
|
+
*
|
|
835
|
+
* @param passwd password to crypt
|
|
836
|
+
* @param algorithm (default as `aes-256-ctr`)
|
|
837
|
+
*/
|
|
838
|
+
crypto3 = (passwd, algorithm) => {
|
|
839
|
+
algorithm = algorithm || 'aes-256-ctr';
|
|
840
|
+
const MAGIC = 'LM!#';
|
|
841
|
+
const VERSION = 'V003';
|
|
842
|
+
const HEAD_B64_LEN = 48; // 36 bytes -> 48 base64 (no padding)
|
|
843
|
+
const errScope = `crypto3(${algorithm}#${VERSION})`;
|
|
844
|
+
const key = Buffer.concat([Buffer.from(passwd)], Buffer.alloc(32).length);
|
|
845
|
+
const hmac = (data, sig) => this.hmac(data, sig, 'sha256', 'hex');
|
|
846
|
+
const currentMs = () => this.current_time_ms(); // 13 digits timestamp
|
|
847
|
+
const makeNonce = () => this.uuid().replace(/-/g, '').substring(0, 13); // 13 chars (52-bit entropy)
|
|
848
|
+
return new (class {
|
|
849
|
+
encrypt = (val, options) => {
|
|
850
|
+
val = val === undefined ? null : val;
|
|
851
|
+
const nonce = options?.nonce ?? makeNonce();
|
|
852
|
+
const timestamp = String(options?.current ?? currentMs()).padStart(13, '0');
|
|
853
|
+
const iv = Buffer.from(hmac(`${nonce}:${timestamp}`, passwd).substring(0, 32), 'hex'); // AES IV must be 16 bytes.
|
|
854
|
+
const buffer = Buffer.from(JSON.stringify({ d: val }), 'utf8');
|
|
855
|
+
const cipher = crypto_1.default.createCipheriv(algorithm, key, iv);
|
|
856
|
+
const crypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
|
|
857
|
+
const headRaw = `${MAGIC}${VERSION}:${nonce}:${timestamp}`;
|
|
858
|
+
const head = Buffer.from(headRaw).toString('base64');
|
|
859
|
+
const body = crypted.toString('base64');
|
|
860
|
+
return [head, body].join('');
|
|
861
|
+
};
|
|
862
|
+
decrypt = (msg, options) => {
|
|
863
|
+
if (!msg)
|
|
864
|
+
throw new Error(`@msg (string) is required - ${errScope}`);
|
|
865
|
+
if (msg.length < HEAD_B64_LEN)
|
|
866
|
+
throw new Error(`400 INVALID DATA - data too short! @${errScope}`);
|
|
867
|
+
// 1. decode base64 header (48 chars -> 36 bytes)
|
|
868
|
+
const headBase64 = msg.substring(0, HEAD_B64_LEN);
|
|
869
|
+
const head = Buffer.from(headBase64, 'base64').toString('utf8');
|
|
870
|
+
if (head.length !== 36)
|
|
871
|
+
throw new Error(`400 INVALID DATA - invalid header! @${errScope}`);
|
|
872
|
+
// 2. validate magic and version
|
|
873
|
+
if (!head.startsWith(MAGIC))
|
|
874
|
+
throw new Error(`400 INVALID MAGIC - invalid magic! @${errScope}`);
|
|
875
|
+
const version = head.substring(4, 8);
|
|
876
|
+
if (version !== VERSION)
|
|
877
|
+
throw new Error(`400 INVALID VERSION - expected ${VERSION}, got ${version}! @${errScope}`);
|
|
878
|
+
// 3. parse nonce, timestamp (format: LM!#V003:nonce:timestamp)
|
|
879
|
+
const [, nonce, timestamp] = head.substring(8).split(':');
|
|
880
|
+
if (!nonce || nonce.length !== 13)
|
|
881
|
+
throw new Error(`400 INVALID DATA - invalid nonce! @${errScope}`);
|
|
882
|
+
if (!timestamp || !/^\d+$/.test(timestamp))
|
|
883
|
+
throw new Error(`400 INVALID DATA - invalid timestamp! @${errScope}`);
|
|
884
|
+
if (options?.maxAge !== undefined) {
|
|
885
|
+
const current = options?.current ?? currentMs();
|
|
886
|
+
if (current - parseInt(timestamp, 10) > options.maxAge)
|
|
887
|
+
throw new Error(`400 INVALID DATA - expired timestamp! @${errScope}`);
|
|
888
|
+
}
|
|
889
|
+
// 4. decrypt
|
|
890
|
+
const iv = Buffer.from(hmac(`${nonce}:${timestamp}`, passwd).substring(0, 32), 'hex');
|
|
891
|
+
const decipher = crypto_1.default.createDecipheriv(algorithm, key, iv);
|
|
892
|
+
const dec = Buffer.concat([
|
|
893
|
+
decipher.update(Buffer.from(msg.substring(HEAD_B64_LEN), 'base64')),
|
|
894
|
+
decipher.final(),
|
|
895
|
+
]).toString('utf8');
|
|
896
|
+
if (!dec.startsWith('{') || !dec.endsWith('}'))
|
|
897
|
+
throw new Error(`400 INVALID PASSWD - invalid json string @${errScope}`);
|
|
898
|
+
const $msg = JSON.parse(dec) || {};
|
|
899
|
+
return $msg?.d;
|
|
900
|
+
};
|
|
901
|
+
})();
|
|
902
|
+
};
|
|
903
|
+
/**
|
|
904
|
+
* encrypt shorthand using crypto3
|
|
905
|
+
*/
|
|
906
|
+
encrypt = (data, secret, options) => {
|
|
907
|
+
return this.crypto3(secret).encrypt(data, options);
|
|
908
|
+
};
|
|
909
|
+
/**
|
|
910
|
+
* decrypt shorthand using crypto3
|
|
911
|
+
*/
|
|
912
|
+
decrypt = (data, secret, options) => {
|
|
913
|
+
return this.crypto3(secret).decrypt(data, options);
|
|
914
|
+
};
|
|
915
|
+
/**
|
|
916
|
+
* builder for `JWTHelper`
|
|
917
|
+
* @param passcode string for verification.
|
|
918
|
+
* @param current_ms (optional) current time in millisecond (required to verify `exp`)
|
|
919
|
+
*/
|
|
920
|
+
jwt = (passcode, current_ms) => {
|
|
921
|
+
const $U = this;
|
|
922
|
+
/**
|
|
923
|
+
* main class.
|
|
924
|
+
*/
|
|
925
|
+
return new (class JWTHelper {
|
|
926
|
+
constructor() { }
|
|
927
|
+
/**
|
|
928
|
+
* use `jsonwebtoken` directly.
|
|
929
|
+
*/
|
|
930
|
+
$ = jsonwebtoken_1.default;
|
|
931
|
+
/**
|
|
932
|
+
* encode object to token string
|
|
933
|
+
* - Synchronous Sign with default (HS256: HMAC SHA256)
|
|
934
|
+
*
|
|
935
|
+
* @param data object
|
|
936
|
+
* @param algorithm algorithm to use
|
|
937
|
+
*/
|
|
938
|
+
encode = (data, algorithm = 'HS256') => {
|
|
939
|
+
data = current_ms ? { ...data, iat: Math.floor(current_ms / 1000) } : data;
|
|
940
|
+
const token = jsonwebtoken_1.default.sign(data, passcode, { algorithm });
|
|
941
|
+
return token;
|
|
942
|
+
};
|
|
943
|
+
/**
|
|
944
|
+
* decode token string
|
|
945
|
+
*
|
|
946
|
+
* @param token string
|
|
947
|
+
*/
|
|
948
|
+
decode = (token, options) => {
|
|
949
|
+
const N = jsonwebtoken_1.default.decode(token, options);
|
|
950
|
+
return N;
|
|
951
|
+
};
|
|
952
|
+
/**
|
|
953
|
+
* verify token
|
|
954
|
+
* - Synchronous Verify with default (HS256: HMAC SHA256)
|
|
955
|
+
*
|
|
956
|
+
* @param token
|
|
957
|
+
* @param algorithm
|
|
958
|
+
* @throws `jwt expired` if exp has expired!.
|
|
959
|
+
*/
|
|
960
|
+
verify = (token, algorithm = 'HS256') => {
|
|
961
|
+
const verified = jsonwebtoken_1.default.verify(token, passcode, { algorithms: [algorithm] });
|
|
962
|
+
const cur = $U.N(current_ms, 0);
|
|
963
|
+
const exp = $U.N(verified?.exp, 0) * 1000;
|
|
964
|
+
if (cur > 0 && exp > 0 && exp < current_ms)
|
|
965
|
+
throw new Error(`jwt expired at ${$U.ts(exp)}`);
|
|
966
|
+
return verified;
|
|
967
|
+
};
|
|
968
|
+
})();
|
|
969
|
+
};
|
|
962
970
|
/**
|
|
963
971
|
* get UUID as `uuid.v4()`
|
|
964
972
|
*/
|