k2hr3-api 1.0.42 → 2.0.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.
Files changed (149) hide show
  1. package/config/k2hr3-init.sh.templ +4 -4
  2. package/dist/.gitkeep +0 -0
  3. package/dist/src/app.js +262 -0
  4. package/{bin → dist/src/bin}/run.sh +1 -1
  5. package/dist/src/bin/watcher.js +113 -0
  6. package/dist/src/bin/www.js +217 -0
  7. package/dist/src/lib/basicipcheck.js +392 -0
  8. package/dist/src/lib/cacerts.js +106 -0
  9. package/dist/src/lib/dbglogging.js +190 -0
  10. package/dist/src/lib/dummyuserapi.js +719 -0
  11. package/dist/src/lib/ipwatch.js +354 -0
  12. package/dist/src/lib/k2hr3acrutil.js +532 -0
  13. package/dist/src/lib/k2hr3apiutil.js +1444 -0
  14. package/dist/src/lib/k2hr3cliutil.js +183 -0
  15. package/dist/src/lib/k2hr3config.js +832 -0
  16. package/dist/src/lib/k2hr3cryptutil.js +258 -0
  17. package/dist/src/lib/k2hr3dkc.js +12121 -0
  18. package/dist/src/lib/k2hr3extdata.js +198 -0
  19. package/dist/src/lib/k2hr3keys.js +207 -0
  20. package/dist/src/lib/k2hr3resutil.js +111 -0
  21. package/dist/src/lib/k2hr3template.js +6546 -0
  22. package/dist/src/lib/k2hr3tokens.js +2643 -0
  23. package/dist/src/lib/k2hr3userdata.js +296 -0
  24. package/dist/src/lib/k8soidc.js +1000 -0
  25. package/dist/src/lib/openstackapiv2.js +695 -0
  26. package/dist/src/lib/openstackapiv3.js +932 -0
  27. package/dist/src/lib/openstackep.js +667 -0
  28. package/{tests/auto_common.js → dist/src/lib/types.js} +4 -38
  29. package/dist/src/routes/acr.js +704 -0
  30. package/dist/src/routes/debugVerify.js +294 -0
  31. package/dist/src/routes/extdata.js +219 -0
  32. package/dist/src/routes/list.js +264 -0
  33. package/dist/src/routes/policy.js +840 -0
  34. package/dist/src/routes/resource.js +1489 -0
  35. package/dist/src/routes/role.js +2627 -0
  36. package/dist/src/routes/service.js +908 -0
  37. package/dist/src/routes/tenant.js +1141 -0
  38. package/dist/src/routes/userTokens.js +482 -0
  39. package/dist/src/routes/userdata.js +212 -0
  40. package/dist/src/routes/version.js +103 -0
  41. package/package.json +152 -121
  42. package/ChangeLog +0 -378
  43. package/app.js +0 -292
  44. package/bin/watcher +0 -122
  45. package/bin/www +0 -180
  46. package/eslint.config.mjs +0 -68
  47. package/lib/basicipcheck.js +0 -376
  48. package/lib/cacerts.js +0 -71
  49. package/lib/dbglogging.js +0 -151
  50. package/lib/dummyuserapi.js +0 -766
  51. package/lib/ipwatch.js +0 -379
  52. package/lib/k2hr3acrutil.js +0 -516
  53. package/lib/k2hr3apiutil.js +0 -1494
  54. package/lib/k2hr3cliutil.js +0 -191
  55. package/lib/k2hr3config.js +0 -826
  56. package/lib/k2hr3cryptutil.js +0 -254
  57. package/lib/k2hr3dkc.js +0 -12632
  58. package/lib/k2hr3extdata.js +0 -198
  59. package/lib/k2hr3keys.js +0 -234
  60. package/lib/k2hr3resutil.js +0 -100
  61. package/lib/k2hr3template.js +0 -6925
  62. package/lib/k2hr3tokens.js +0 -2799
  63. package/lib/k2hr3userdata.js +0 -312
  64. package/lib/k8soidc.js +0 -1012
  65. package/lib/openstackapiv2.js +0 -764
  66. package/lib/openstackapiv3.js +0 -1032
  67. package/lib/openstackep.js +0 -553
  68. package/routes/acr.js +0 -738
  69. package/routes/debugVerify.js +0 -263
  70. package/routes/extdata.js +0 -232
  71. package/routes/list.js +0 -270
  72. package/routes/policy.js +0 -869
  73. package/routes/resource.js +0 -1441
  74. package/routes/role.js +0 -2664
  75. package/routes/service.js +0 -894
  76. package/routes/tenant.js +0 -1095
  77. package/routes/userTokens.js +0 -511
  78. package/routes/userdata.js +0 -218
  79. package/routes/version.js +0 -108
  80. package/templ/Dockerfile.templ +0 -71
  81. package/tests/auto_acr.js +0 -1101
  82. package/tests/auto_acr_spec.js +0 -79
  83. package/tests/auto_all_spec.js +0 -142
  84. package/tests/auto_control_subprocess.sh +0 -243
  85. package/tests/auto_extdata.js +0 -220
  86. package/tests/auto_extdata_spec.js +0 -79
  87. package/tests/auto_init_config_json.sh +0 -275
  88. package/tests/auto_k2hdkc_server.ini +0 -109
  89. package/tests/auto_k2hdkc_slave.ini +0 -83
  90. package/tests/auto_list.js +0 -439
  91. package/tests/auto_list_spec.js +0 -79
  92. package/tests/auto_policy.js +0 -1579
  93. package/tests/auto_policy_spec.js +0 -79
  94. package/tests/auto_resource.js +0 -10956
  95. package/tests/auto_resource_spec.js +0 -79
  96. package/tests/auto_role.js +0 -6150
  97. package/tests/auto_role_spec.js +0 -79
  98. package/tests/auto_service.js +0 -770
  99. package/tests/auto_service_spec.js +0 -79
  100. package/tests/auto_subprocesses.js +0 -114
  101. package/tests/auto_template.sh +0 -126
  102. package/tests/auto_tenant.js +0 -1100
  103. package/tests/auto_tenant_spec.js +0 -79
  104. package/tests/auto_token_util.js +0 -219
  105. package/tests/auto_userdata.js +0 -292
  106. package/tests/auto_userdata_spec.js +0 -79
  107. package/tests/auto_usertokens.js +0 -565
  108. package/tests/auto_usertokens_spec.js +0 -79
  109. package/tests/auto_version.js +0 -127
  110. package/tests/auto_version_spec.js +0 -79
  111. package/tests/auto_watcher.js +0 -157
  112. package/tests/auto_watcher_spec.js +0 -79
  113. package/tests/k2hdkc_test.data +0 -986
  114. package/tests/k2hdkc_test_load.sh +0 -255
  115. package/tests/k2hr3template_test.js +0 -187
  116. package/tests/k2hr3template_test.sh +0 -339
  117. package/tests/k2hr3template_test_async.js +0 -216
  118. package/tests/k2hr3template_test_template.result +0 -7117
  119. package/tests/k2hr3template_test_template.txt +0 -3608
  120. package/tests/k2hr3template_test_vars.js +0 -194
  121. package/tests/manual_acr_delete.js +0 -143
  122. package/tests/manual_acr_get.js +0 -297
  123. package/tests/manual_acr_postput.js +0 -215
  124. package/tests/manual_allusertenant_get.js +0 -113
  125. package/tests/manual_extdata_get.js +0 -191
  126. package/tests/manual_k2hr3keys_get.js +0 -84
  127. package/tests/manual_list_gethead.js +0 -230
  128. package/tests/manual_policy_delete.js +0 -132
  129. package/tests/manual_policy_gethead.js +0 -275
  130. package/tests/manual_policy_postput.js +0 -297
  131. package/tests/manual_resource_delete.js +0 -433
  132. package/tests/manual_resource_gethead.js +0 -423
  133. package/tests/manual_resource_postput.js +0 -487
  134. package/tests/manual_role_delete.js +0 -404
  135. package/tests/manual_role_gethead.js +0 -547
  136. package/tests/manual_role_postput.js +0 -544
  137. package/tests/manual_service_delete.js +0 -153
  138. package/tests/manual_service_gethead.js +0 -178
  139. package/tests/manual_service_postput.js +0 -348
  140. package/tests/manual_tenant_delete.js +0 -186
  141. package/tests/manual_tenant_gethead.js +0 -268
  142. package/tests/manual_tenant_postput.js +0 -293
  143. package/tests/manual_test.sh +0 -352
  144. package/tests/manual_userdata_get.js +0 -173
  145. package/tests/manual_usertoken_gethead.js +0 -136
  146. package/tests/manual_usertoken_postput.js +0 -310
  147. package/tests/manual_version_get.js +0 -127
  148. package/tests/run_local_test_k2hdkc.sh +0 -174
  149. package/tests/test.sh +0 -333
@@ -0,0 +1,1444 @@
1
+ "use strict";
2
+ /*
3
+ * K2HR3 REST API
4
+ *
5
+ * Copyright 2017 Yahoo Japan Corporation.
6
+ *
7
+ * K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
8
+ * common management information for the cloud.
9
+ * K2HR3 can dynamically manage information as "who", "what", "operate".
10
+ * These are stored as roles, resources, policies in K2hdkc, and the
11
+ * client system can dynamically read and modify these information.
12
+ *
13
+ * For the full copyright and license information, please view
14
+ * the license file that was distributed with this source code.
15
+ *
16
+ * AUTHOR: Takeshi Nakatani
17
+ * CREATE: Wed Jun 8 2017
18
+ * REVISION:
19
+ *
20
+ */
21
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ var desc = Object.getOwnPropertyDescriptor(m, k);
24
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
25
+ desc = { enumerable: true, get: function() { return m[k]; } };
26
+ }
27
+ Object.defineProperty(o, k2, desc);
28
+ }) : (function(o, m, k, k2) {
29
+ if (k2 === undefined) k2 = k;
30
+ o[k2] = m[k];
31
+ }));
32
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
33
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34
+ }) : function(o, v) {
35
+ o["default"] = v;
36
+ });
37
+ var __importStar = (this && this.__importStar) || (function () {
38
+ var ownKeys = function(o) {
39
+ ownKeys = Object.getOwnPropertyNames || function (o) {
40
+ var ar = [];
41
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
42
+ return ar;
43
+ };
44
+ return ownKeys(o);
45
+ };
46
+ return function (mod) {
47
+ if (mod && mod.__esModule) return mod;
48
+ var result = {};
49
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
50
+ __setModuleDefault(result, mod);
51
+ return result;
52
+ };
53
+ })();
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.k2hr3ppiutil = void 0;
56
+ const dns = __importStar(require("dns"));
57
+ const fs = __importStar(require("fs"));
58
+ const crypto = __importStar(require("crypto"));
59
+ const url = __importStar(require("url"));
60
+ //---------------------------------------------------------
61
+ // Utilities for variables
62
+ //---------------------------------------------------------
63
+ const rawIsSafeEntity = (data) => {
64
+ return (undefined !== data && null !== data);
65
+ };
66
+ const rawIsString = (str) => {
67
+ return (undefined !== str && null !== str && 'string' === typeof str);
68
+ };
69
+ const rawIsSafeString = (str) => {
70
+ return (undefined !== str && null !== str && 'string' === typeof str && 0 < str.length);
71
+ };
72
+ const rawIsPlainObject = (data) => {
73
+ return (undefined !== data && null !== data && 'object' === typeof data && !Array.isArray(data));
74
+ };
75
+ const rawIsValTypeAllObject = (val) => {
76
+ if (!rawIsPlainObject(val)) {
77
+ return false;
78
+ }
79
+ for (const [, value] of Object.entries(val)) {
80
+ if (!rawIsValTypeAll(value)) {
81
+ return false;
82
+ }
83
+ }
84
+ return true;
85
+ };
86
+ const rawIsValTypeAll = (val) => {
87
+ if (null === val) {
88
+ return true;
89
+ }
90
+ else if (rawIsBoolean(val) || rawIsSafeNumber(val) || rawIsString(val)) {
91
+ return true;
92
+ }
93
+ else if (rawIsArray(val)) {
94
+ return val.every((element) => rawIsValTypeAll(element));
95
+ }
96
+ else if ('object' === typeof val) {
97
+ return rawIsValTypeAllObject(val);
98
+ }
99
+ else {
100
+ return false;
101
+ }
102
+ };
103
+ const rawIsFunction = (val) => {
104
+ return (undefined !== val && null !== val && 'function' === typeof val);
105
+ };
106
+ const rawIsBoolean = (val) => {
107
+ return (undefined !== val && null !== val && 'boolean' === typeof val);
108
+ };
109
+ const rawIsSafeNumber = (num) => {
110
+ return (undefined !== num && null !== num && 'number' === typeof num && Number.isFinite(num)); // except NaN and Infinity
111
+ };
112
+ const numericStringRegex = /^[+-]?(?:\d+|\d*\.\d+)(?:[eE][+-]?\d+)?$/;
113
+ const rawIsSafeNumeric = (strnum) => {
114
+ if (rawIsSafeNumber(strnum)) {
115
+ return true;
116
+ }
117
+ else if (rawIsSafeString(strnum)) {
118
+ const tmp = strnum.trim();
119
+ if (0 === tmp.length || !numericStringRegex.test(tmp)) {
120
+ return false;
121
+ }
122
+ return Number.isFinite(Number(tmp));
123
+ }
124
+ return false;
125
+ };
126
+ const rawCvtToNumber = (num) => {
127
+ if (rawIsSafeNumber(num)) {
128
+ return num;
129
+ }
130
+ else if (rawIsSafeString(num) && rawIsSafeNumeric(num)) {
131
+ return Number(num.trim());
132
+ }
133
+ return null;
134
+ };
135
+ const rawCompareCaseString = (str1, str2) => {
136
+ if (rawIsSafeString(str1) && rawIsSafeString(str2) && str1.toLowerCase() === str2.toLowerCase()) {
137
+ return true;
138
+ }
139
+ return false;
140
+ };
141
+ const rawIsArray = (arr) => {
142
+ return Array.isArray(arr);
143
+ };
144
+ const rawIsReadonlyArray = (arr) => {
145
+ return Array.isArray(arr);
146
+ };
147
+ const rawIsStringArray = (arr) => {
148
+ return (Array.isArray(arr) && arr.every((element) => rawIsString(element)));
149
+ };
150
+ const rawIsString2DArray = (arr) => {
151
+ return rawIsArray(arr) && arr.every((row) => rawIsArray(row) && row.every((it) => rawIsString(it)));
152
+ };
153
+ const rawHasPartString = (strbase, sep, values, iscase) => {
154
+ if (!rawIsSafeString(strbase) || !rawIsSafeString(sep)) {
155
+ return false;
156
+ }
157
+ let valarray = [];
158
+ if (rawIsSafeString(values)) {
159
+ valarray.push(values);
160
+ }
161
+ else if (rawIsArray(values)) {
162
+ valarray = values;
163
+ }
164
+ else {
165
+ return false;
166
+ }
167
+ if (!rawIsBoolean(iscase)) {
168
+ iscase = true;
169
+ }
170
+ const basearray = strbase.split(sep);
171
+ for (let cnt1 = 0; cnt1 < basearray.length; ++cnt1) {
172
+ const strtmp1 = basearray[cnt1].trim();
173
+ if (!rawIsSafeString(strtmp1)) {
174
+ continue;
175
+ }
176
+ for (let cnt2 = 0; cnt2 < valarray.length; ++cnt2) {
177
+ const strtmp2 = valarray[cnt2].trim();
178
+ if (!rawIsSafeString(strtmp2)) {
179
+ continue;
180
+ }
181
+ if (iscase) {
182
+ if (rawCompareCaseString(strtmp1, strtmp2)) {
183
+ return true;
184
+ }
185
+ }
186
+ else {
187
+ if (strtmp1 === strtmp2) {
188
+ return true;
189
+ }
190
+ }
191
+ }
192
+ }
193
+ return false;
194
+ };
195
+ const rawGetSafeString = (str) => {
196
+ if (rawIsSafeString(str)) {
197
+ return str;
198
+ }
199
+ return '';
200
+ };
201
+ const rawCheckSimpleJSON = (str) => {
202
+ if (!rawIsString(str)) {
203
+ return false;
204
+ }
205
+ try {
206
+ JSON.parse(str);
207
+ return true;
208
+ }
209
+ catch {
210
+ return false;
211
+ }
212
+ };
213
+ const rawParseJSON = (str) => {
214
+ if (!rawIsString(str)) {
215
+ return null;
216
+ }
217
+ try {
218
+ return JSON.parse(str);
219
+ }
220
+ catch {
221
+ return null;
222
+ }
223
+ };
224
+ const rawIsNotEmptyArray = (arr) => {
225
+ return (Array.isArray(arr) && 0 !== arr.length);
226
+ };
227
+ const rawGetSafeArray = (arr) => {
228
+ return Array.isArray(arr) ? arr.slice() : [];
229
+ };
230
+ const rawGetSafeStringArray = (arr) => {
231
+ if (rawIsSafeString(arr)) {
232
+ return [arr];
233
+ }
234
+ else if (rawIsStringArray(arr)) {
235
+ return arr.slice();
236
+ }
237
+ return [];
238
+ };
239
+ const rawFindStringInArray = (arr, str) => {
240
+ if (!rawIsReadonlyArray(arr)) {
241
+ return false;
242
+ }
243
+ if (!rawIsSafeString(str)) {
244
+ return false;
245
+ }
246
+ return arr.includes(str);
247
+ };
248
+ const rawAddStringToArray = (arr, str) => {
249
+ if (!rawIsSafeString(str)) {
250
+ return [];
251
+ }
252
+ if (!rawIsArray(arr)) {
253
+ return [str];
254
+ }
255
+ return arr.concat(str);
256
+ };
257
+ const rawTryAddStringToArray = (arr, str) => {
258
+ if (!rawIsSafeString(str)) {
259
+ return false;
260
+ }
261
+ if (!rawIsArray(arr)) {
262
+ return false;
263
+ }
264
+ if (rawFindStringInArray(arr, str)) {
265
+ return false;
266
+ }
267
+ try {
268
+ arr.push(str);
269
+ return true;
270
+ }
271
+ catch {
272
+ return false;
273
+ }
274
+ };
275
+ const rawRemoveStringFromArray = (arr, str) => {
276
+ if (!rawIsArray(arr) || !rawIsSafeString(str)) {
277
+ return false;
278
+ }
279
+ const idx = arr.indexOf(str);
280
+ if (-1 === idx) {
281
+ return false;
282
+ }
283
+ try {
284
+ arr.splice(idx, 1);
285
+ return true;
286
+ }
287
+ catch {
288
+ return false;
289
+ }
290
+ };
291
+ const rawCompareArray = (arr1, arr2, strict) => {
292
+ if (!rawIsArray(arr1) || !rawIsArray(arr2)) {
293
+ return false;
294
+ }
295
+ if (arr1.length !== arr2.length) {
296
+ return false;
297
+ }
298
+ if (rawIsBoolean(strict) && true === strict) {
299
+ return (JSON.stringify(arr1) === JSON.stringify(arr2));
300
+ }
301
+ else {
302
+ const keyCountMap = new Map();
303
+ for (const value1 of arr1) {
304
+ const key = JSON.stringify(value1);
305
+ keyCountMap.set(key, (keyCountMap.get(key) ?? 0) + 1);
306
+ }
307
+ for (const value2 of arr2) {
308
+ const key = JSON.stringify(value2);
309
+ const count = keyCountMap.get(key);
310
+ if (!count) {
311
+ return false;
312
+ }
313
+ if (1 === count) {
314
+ keyCountMap.delete(key);
315
+ }
316
+ else {
317
+ keyCountMap.set(key, count - 1);
318
+ }
319
+ }
320
+ return (0 === keyCountMap.size);
321
+ }
322
+ };
323
+ const rawMergeArray = (arr1, arr2) => {
324
+ if (!rawIsArray(arr1) || !rawIsArray(arr2)) {
325
+ return [];
326
+ }
327
+ if (!rawIsArray(arr1)) {
328
+ return arr2.slice();
329
+ }
330
+ if (!rawIsArray(arr2)) {
331
+ return arr1.slice();
332
+ }
333
+ const result = arr1.slice();
334
+ const seen = new Set(result);
335
+ for (const value of arr2) {
336
+ if (!seen.has(value)) {
337
+ seen.add(value);
338
+ result.push(value);
339
+ }
340
+ }
341
+ return result;
342
+ };
343
+ //
344
+ // Get difference from base to new array elements.
345
+ // If is_deleted_element is true, returns result difference elements for deleting from base.
346
+ // If is_deleted_element is false, returns result difference elements for adding from base.
347
+ //
348
+ const rawGetDiffArray = (basearr, newarr, is_deleted_element) => {
349
+ const barr = rawIsArray(basearr) ? basearr : [];
350
+ const narr = rawIsArray(newarr) ? newarr : [];
351
+ if (!rawIsNotEmptyArray(barr) && !rawIsNotEmptyArray(narr)) {
352
+ return [];
353
+ }
354
+ else if (!rawIsNotEmptyArray(barr) && rawIsNotEmptyArray(narr)) {
355
+ return is_deleted_element ? [] : narr.slice();
356
+ }
357
+ else if (rawIsNotEmptyArray(barr) && !rawIsNotEmptyArray(narr)) {
358
+ return is_deleted_element ? barr.slice() : [];
359
+ }
360
+ if (is_deleted_element) {
361
+ const seenNew = new Set(narr);
362
+ const result = [];
363
+ for (const value of barr) {
364
+ if (!seenNew.has(value)) {
365
+ result.push(value);
366
+ }
367
+ }
368
+ return result;
369
+ }
370
+ else {
371
+ const seenBase = new Set(barr);
372
+ const result = [];
373
+ for (const value of narr) {
374
+ if (!seenBase.has(value)) {
375
+ result.push(value);
376
+ }
377
+ }
378
+ return result;
379
+ }
380
+ };
381
+ const rawMergeObjects = (obj1, obj2) => {
382
+ const localSafeKey = (key) => {
383
+ return ('__proto__' !== key && 'constructor' !== key && 'prototype' !== key);
384
+ };
385
+ const _obj1 = rawIsPlainObject(obj1) ? obj1 : {};
386
+ const _obj2 = rawIsPlainObject(obj2) ? obj2 : {};
387
+ const resobj = {};
388
+ for (const key of Object.keys(_obj1)) {
389
+ if (localSafeKey(key)) {
390
+ resobj[key] = _obj1[key];
391
+ }
392
+ }
393
+ for (const key of Object.keys(_obj2)) {
394
+ if (localSafeKey(key)) {
395
+ resobj[key] = _obj2[key];
396
+ }
397
+ }
398
+ return resobj;
399
+ };
400
+ const rawMergeValTypeAllObject = (obj1, obj2) => {
401
+ const localSafeKey = (key) => {
402
+ return ('__proto__' !== key && 'constructor' !== key && 'prototype' !== key);
403
+ };
404
+ const _obj1 = rawIsValTypeAllObject(obj1) ? obj1 : {};
405
+ const _obj2 = rawIsValTypeAllObject(obj2) ? obj2 : {};
406
+ const resobj = {};
407
+ // copy entries from obj1
408
+ for (const key of Object.keys(_obj1)) {
409
+ if (localSafeKey(key)) {
410
+ const val = _obj1[key];
411
+ resobj[key] = rawIsValTypeAll(val) ? val : null;
412
+ }
413
+ }
414
+ // copy/overwrite entries from obj2
415
+ for (const key of Object.keys(_obj2)) {
416
+ if (localSafeKey(key)) {
417
+ const val = _obj2[key];
418
+ resobj[key] = rawIsValTypeAll(val) ? val : null;
419
+ }
420
+ }
421
+ return resobj;
422
+ };
423
+ //---------------------------------------------------------
424
+ // Utilities for time
425
+ //---------------------------------------------------------
426
+ //
427
+ // base is UTC
428
+ //
429
+ const rawConvertUnixtime = (base) => {
430
+ let unixtime_ms;
431
+ if (!rawIsSafeString(base)) {
432
+ unixtime_ms = Date.now();
433
+ }
434
+ else {
435
+ const trimBase = base.trim();
436
+ const tmp_ms = new Date(trimBase).getTime();
437
+ unixtime_ms = Number.isFinite(tmp_ms) ? tmp_ms : Date.now();
438
+ }
439
+ return Math.floor(unixtime_ms / 1000);
440
+ };
441
+ const rawCalcExpire = (expiredate) => {
442
+ let expire = rawConvertUnixtime(expiredate) - rawConvertUnixtime();
443
+ if (expire < 0) {
444
+ expire = 0;
445
+ }
446
+ return expire;
447
+ };
448
+ const rawIsExpired = (base) => {
449
+ return (rawConvertUnixtime(base) < rawConvertUnixtime()); // base(UTC ISO 8601) < now
450
+ };
451
+ const rawConvertISOStringToUnixtime = (iso) => {
452
+ if (!rawIsSafeString(iso)) {
453
+ return 0;
454
+ }
455
+ const isoBase = iso.trim();
456
+ const tmp_ms = new Date(isoBase).getTime();
457
+ const iso_ms = Number.isFinite(tmp_ms) ? tmp_ms : Date.now();
458
+ return Math.floor(iso_ms / 1000);
459
+ };
460
+ const rawGetExpireUnixtime = (starttime, expiretime) => {
461
+ return (expiretime - starttime);
462
+ };
463
+ const rawGetExpireUnixtimeFromISOStrings = (startiso, expireiso) => {
464
+ const starttime = rawConvertISOStringToUnixtime(startiso);
465
+ const expiretime = rawConvertISOStringToUnixtime(expireiso);
466
+ return rawGetExpireUnixtime(starttime, expiretime);
467
+ };
468
+ //---------------------------------------------------------
469
+ // Utilities for Key and Hierarchy
470
+ //---------------------------------------------------------
471
+ //
472
+ // Convert string to Hierarchy Array by separator
473
+ // ex) "parent-", "a/b/c" => ["parent-", "parent-a", "parent-a/b", "parent-a/b/c"]
474
+ // null, "a/b/c" => ["a", "a/b", "a/b/c"]
475
+ //
476
+ const rawExpandHierarchyArray = (parent, str, separator, allow_empty) => {
477
+ if (!rawIsSafeString(str)) {
478
+ return null;
479
+ }
480
+ const sep = rawIsSafeString(separator) ? separator : '/';
481
+ if (!rawIsSafeEntity(allow_empty)) {
482
+ allow_empty = false;
483
+ }
484
+ else if (!rawIsBoolean(allow_empty)) {
485
+ return null;
486
+ }
487
+ const result = [];
488
+ let tmp = '';
489
+ if (rawIsSafeString(parent)) {
490
+ result.push(parent);
491
+ tmp = parent;
492
+ }
493
+ const parts = str.split(sep);
494
+ for (let cnt = 0; cnt < parts.length; ++cnt) {
495
+ if (0 !== cnt) {
496
+ tmp += sep;
497
+ }
498
+ const tmpstr = rawGetSafeString(parts[cnt]);
499
+ tmp += tmpstr;
500
+ if (allow_empty || '' !== tmp) {
501
+ result.push(tmp);
502
+ }
503
+ }
504
+ return result;
505
+ };
506
+ //
507
+ // Convert parent and terminal children(string or array) to Hierarchy object
508
+ // The result is the object which is configured "key=parent", "value=parent's children".
509
+ //
510
+ // ex) parent = "parent-" ===> result = { "parent": ["parent-a"],
511
+ // children = "a/b/c" "parent-a": ["parent-a/b"],
512
+ // "parent-a/b": ["parent-a/b/c"],
513
+ // "parent-a/b/c": []
514
+ // };
515
+ //
516
+ // ex) parent = "parent-" ===> result = { "parent": ["parent-a", "parent-1"],
517
+ // children = [ "a/b/c", "parent-a": ["parent-a/b"],
518
+ // "1/2/3"] "parent-a/b": ["parent-a/b/c"],
519
+ // "parent-a/b/c": [],
520
+ // "parent-1": ["parent-1/2"],
521
+ // "parent-1/2": ["parent-1/2/3"],
522
+ // "parent-1/2/3": []
523
+ // };
524
+ //
525
+ // ex) parent = "" ===> result = { "a": ["a/b"],
526
+ // children = ["a/b/c"] "a/b": ["a/b/c"],
527
+ // "a/b/c": []
528
+ // };
529
+ //
530
+ // ex) parent = "" ===> result = null(because this case does not have hierarchy)
531
+ // children = "a"
532
+ //
533
+ const rawExpandHierarchy = (parent, children, separator, allow_empty) => {
534
+ if (!rawIsSafeString(parent)) {
535
+ parent = '';
536
+ }
537
+ let tmpchildren;
538
+ if (Array.isArray(children)) {
539
+ tmpchildren = children.slice();
540
+ }
541
+ else if (rawIsSafeString(children)) {
542
+ tmpchildren = [children];
543
+ }
544
+ else {
545
+ return null;
546
+ }
547
+ let is_set = false;
548
+ const result = {};
549
+ let parent_in_array;
550
+ for (let cnt = 0; cnt < tmpchildren.length; ++cnt) {
551
+ // parent + tmpchildren[x] ---> ["parent", "parent child1", "parent child1 sep child2", ...]
552
+ const child_hierarchy_arr = rawExpandHierarchyArray(parent, tmpchildren[cnt], separator, allow_empty);
553
+ if (null === child_hierarchy_arr || !Array.isArray(child_hierarchy_arr) || 0 === child_hierarchy_arr.length) {
554
+ continue;
555
+ }
556
+ parent_in_array = '';
557
+ for (let cnt2 = 0; cnt2 < child_hierarchy_arr.length; ++cnt2) {
558
+ if ('' !== parent_in_array) {
559
+ // parent ---> [child, child, ...]
560
+ if (!rawFindStringInArray(result[parent_in_array], child_hierarchy_arr[cnt2])) {
561
+ result[parent_in_array].push(child_hierarchy_arr[cnt2]);
562
+ is_set = true;
563
+ }
564
+ }
565
+ parent_in_array = child_hierarchy_arr[cnt2];
566
+ if (!rawIsSafeEntity(result[parent_in_array]) || !Array.isArray(result[parent_in_array])) {
567
+ result[parent_in_array] = new Array(0);
568
+ }
569
+ }
570
+ }
571
+ return (is_set ? result : null);
572
+ };
573
+ //
574
+ // Get direct parent path for key
575
+ // ex) parent: "parent", childkey: ":a/b/c" => parent:a/b
576
+ // parent: null, childkey: ":a/b/c" => :a/b
577
+ // parent: "parent", childkey: ":a" => parent
578
+ // parent: "parent", childkey: "" => null
579
+ //
580
+ const rawGetParentKey = (parent, childkey, separator, allow_empty) => {
581
+ if (!rawIsSafeString(childkey)) {
582
+ return null;
583
+ }
584
+ const child_hierarchy_arr = rawExpandHierarchyArray(parent, childkey, separator, allow_empty);
585
+ if (null === child_hierarchy_arr || !Array.isArray(child_hierarchy_arr) || 0 === child_hierarchy_arr.length) {
586
+ return null;
587
+ }
588
+ if (1 === child_hierarchy_arr.length) {
589
+ // there is no parent, the array is only childkey(or parent)
590
+ return null;
591
+ }
592
+ return child_hierarchy_arr[child_hierarchy_arr.length - 2];
593
+ };
594
+ //
595
+ // Get parent path from string
596
+ //
597
+ // ex) "a/b/c" => "a/b"
598
+ // "a" => null
599
+ // "a/b/c/" => "a/b" : if allow_empty is false
600
+ // "a/b/c/" => "a/b/c" : if allow_empty is true
601
+ // "a//b/c" => "a//b"
602
+ // "a/b/c//" => "a/b" : if allow_empty is false
603
+ // "a/b/c//" => "a/b/c/" : if allow_empty is true
604
+ // "a/" => null : if allow_empty is false
605
+ // "a/" => "a" : if allow_empty is true
606
+ // "/a/b" => "/a"
607
+ // "/a" => null
608
+ // "a//b" => "a" : if allow_empty is false
609
+ // "a//b" => "a/" : if allow_empty is true
610
+ // "a/b///" => "a" : if allow_empty is false
611
+ // "a/b///" => "a/b//" : if allow_empty is true
612
+ //
613
+ const rawGetParentPath = (str, separator, allow_empty) => {
614
+ if (!rawIsSafeString(str)) {
615
+ return '';
616
+ }
617
+ if (!rawIsSafeEntity(allow_empty)) {
618
+ allow_empty = false;
619
+ }
620
+ else if (!rawIsBoolean(allow_empty)) {
621
+ return '';
622
+ }
623
+ if (!rawIsSafeString(separator)) {
624
+ separator = '/';
625
+ }
626
+ // escape if allow empty
627
+ if (allow_empty) {
628
+ // escape '\' --> '\\'
629
+ str = str.replace(/\\/g, '\\\\');
630
+ // last word is '/' --> add '\'
631
+ if ('/' === str[str.length - 1]) {
632
+ str += '\\';
633
+ }
634
+ // if '//' --> '/\/'
635
+ let tmp = '';
636
+ for (let cnt = 0; cnt < str.length; ++cnt) {
637
+ tmp += str[cnt];
638
+ if ('/' === str[cnt] && (cnt + 1) < str.length && '/' === str[cnt + 1]) {
639
+ tmp += '\\';
640
+ }
641
+ }
642
+ str = tmp;
643
+ }
644
+ // parse by separator
645
+ const parts = str.split(separator);
646
+ // remove last elements until it is not empty
647
+ while (0 < parts.length && !rawIsSafeString(parts[parts.length - 1])) {
648
+ parts.pop();
649
+ }
650
+ // remove last element
651
+ if (0 < parts.length) {
652
+ parts.pop();
653
+ }
654
+ // remove last elements until it is not empty
655
+ while (0 < parts.length && !rawIsSafeString(parts[parts.length - 1])) {
656
+ parts.pop();
657
+ }
658
+ // join with separator
659
+ let parent = parts.join(separator);
660
+ // unescape if allow empty
661
+ if (allow_empty && rawIsSafeString(parent)) {
662
+ // '\' --> '' or '\\' --> '\'
663
+ let tmp = '';
664
+ for (let cnt = 0; cnt < parent.length; ++cnt) {
665
+ if ('\\' === parent[cnt]) {
666
+ ++cnt;
667
+ if (cnt < parent.length && '\\' === parent[cnt]) {
668
+ tmp += parent[cnt]; // = '\'
669
+ }
670
+ }
671
+ else {
672
+ tmp += parent[cnt];
673
+ }
674
+ }
675
+ parent = tmp;
676
+ }
677
+ return parent;
678
+ };
679
+ //
680
+ // Compare string by regex or string patterns(array)
681
+ //
682
+ const rawCompareStringByFormats = (str, regex_ptn, pattern_array) => {
683
+ if (!rawIsSafeString(str)) {
684
+ return null;
685
+ }
686
+ const tmpstr = str.toLowerCase();
687
+ if (regex_ptn && rawIsSafeEntity(regex_ptn)) {
688
+ const matches = tmpstr.match(regex_ptn);
689
+ if (null !== matches && rawIsNotEmptyArray(matches) && 2 <= matches.length) {
690
+ return tmpstr;
691
+ }
692
+ }
693
+ let local_ptnarr = [];
694
+ if (rawIsSafeString(pattern_array)) {
695
+ local_ptnarr = [pattern_array];
696
+ }
697
+ else if (rawIsArray(pattern_array)) {
698
+ local_ptnarr = pattern_array;
699
+ }
700
+ for (let cnt = 0; cnt < local_ptnarr.length; ++cnt) {
701
+ if (rawCompareCaseString(tmpstr, local_ptnarr[cnt])) {
702
+ return tmpstr;
703
+ }
704
+ }
705
+ return null;
706
+ };
707
+ //---------------------------------------------------------
708
+ // Utilities for regex
709
+ //---------------------------------------------------------
710
+ //
711
+ // return object = {
712
+ // result: true/false
713
+ // parameter: object(array) or null or '' or undefined
714
+ // }
715
+ //
716
+ const rawGetNormalizeParameter = (parameter, regex_ptn, pattern) => {
717
+ const resobj = { result: false, parameter: undefined };
718
+ if (rawIsSafeString(parameter) && rawCheckSimpleJSON(parameter)) {
719
+ parameter = JSON.parse(parameter);
720
+ }
721
+ if (!rawIsSafeEntity(parameter)) {
722
+ resobj.result = true;
723
+ resobj.parameter = null; // = not update type
724
+ }
725
+ else if (rawIsArray(parameter)) {
726
+ if (!rawIsNotEmptyArray(parameter)) {
727
+ resobj.result = true;
728
+ resobj.parameter = ''; // = clean up type
729
+ }
730
+ else {
731
+ resobj.result = true;
732
+ resobj.parameter = [];
733
+ for (let cnt = 0; cnt < parameter.length; ++cnt) {
734
+ const resstr = rawCompareStringByFormats(parameter[cnt], regex_ptn, pattern);
735
+ if (null === resstr) {
736
+ resobj.result = false;
737
+ resobj.parameter = null;
738
+ break;
739
+ }
740
+ resobj.parameter.push(resstr);
741
+ }
742
+ }
743
+ }
744
+ else if ('' === parameter) {
745
+ resobj.result = true;
746
+ resobj.parameter = ''; // = clean up type
747
+ }
748
+ else if (rawIsSafeString(parameter)) {
749
+ const tmparr = parameter.split(',');
750
+ if (rawIsArray(tmparr) && rawIsNotEmptyArray(tmparr)) {
751
+ resobj.result = true;
752
+ resobj.parameter = [];
753
+ for (let cnt = 0; cnt < tmparr.length; ++cnt) {
754
+ const resstr = rawCompareStringByFormats(tmparr[cnt], regex_ptn, pattern);
755
+ if (null === resstr) {
756
+ resobj.result = false;
757
+ resobj.parameter = null;
758
+ break;
759
+ }
760
+ resobj.parameter.push(resstr);
761
+ }
762
+ }
763
+ else {
764
+ resobj.result = true;
765
+ resobj.parameter = ''; // = clean up type
766
+ }
767
+ }
768
+ else {
769
+ resobj.result = false;
770
+ }
771
+ return resobj;
772
+ };
773
+ //---------------------------------------------------------
774
+ // Utilities for UUID4
775
+ //---------------------------------------------------------
776
+ // RFC4122
777
+ // https://www.ietf.org/rfc/rfc4122.txt
778
+ //
779
+ // UUID4 = xxxxxxxx-xxxx-Nxxx-Mxxx-xxxxxxxxxxxx
780
+ // N: 0x4X
781
+ // M: 0x{8,9,A,B}X
782
+ //
783
+ const rawGetBinUuid4 = () => {
784
+ const binUuid4 = crypto.randomBytes(16);
785
+ binUuid4[6] = (binUuid4[6] & 0x0f) | 0x40; // UUID4 must be 0x4X for pos 6 in buffer
786
+ binUuid4[8] = (binUuid4[8] & 0x3f) | 0x80; // UUID4 must be 0x{8,9,A,B}X for pos 8 in buffer
787
+ return binUuid4;
788
+ };
789
+ // [NOTE]
790
+ // If binary data is given, this is only a conversion to UUID format,
791
+ // not a method that enforces UUID4 format.
792
+ //
793
+ const rawGetStrUuid4 = (binUuid4) => {
794
+ const buf = Buffer.isBuffer(binUuid4) ? binUuid4 : rawGetBinUuid4();
795
+ if (!Buffer.isBuffer(buf) || buf.length < 16) {
796
+ return '';
797
+ }
798
+ const hex = buf.toString('hex'); // 16 bytes to over 32 characters
799
+ if (hex.length < 32) {
800
+ return '';
801
+ }
802
+ return [hex.slice(0, 8), hex.slice(8, 12), hex.slice(12, 16), hex.slice(16, 20), hex.slice(20, 32)].join('-');
803
+ };
804
+ const rawIsSafeStrUuid4 = (strUuid4) => {
805
+ if (!rawIsSafeString(strUuid4)) {
806
+ return false;
807
+ }
808
+ // split '-' separator and check each part
809
+ const strArray = strUuid4.split('-');
810
+ if (5 != strArray.length ||
811
+ 0 == strArray[0].length || 8 < strArray[0].length ||
812
+ 0 == strArray[1].length || 4 < strArray[1].length ||
813
+ 0 == strArray[2].length || 4 < strArray[2].length ||
814
+ 0 == strArray[3].length || 4 < strArray[3].length ||
815
+ 0 == strArray[4].length || 12 < strArray[4].length) {
816
+ return false;
817
+ }
818
+ return true;
819
+ };
820
+ const rawFillZeroString = (str, size) => {
821
+ if (!rawIsSafeString(str)) {
822
+ return null;
823
+ }
824
+ if (!Number.isInteger(size) || size < str.length) {
825
+ return null;
826
+ }
827
+ return str.length < size ? str.padStart(size, '0') : str;
828
+ };
829
+ const rawCvtStrToBinUuid4 = (strUuid4) => {
830
+ if (!rawIsSafeString(strUuid4)) {
831
+ return null;
832
+ }
833
+ // split '-' separator
834
+ const strArray = strUuid4.split('-');
835
+ if (5 !== strArray.length) {
836
+ return null;
837
+ }
838
+ // check length and fill '0' for short part
839
+ strArray[0] = rawFillZeroString(strArray[0], 8) ?? '';
840
+ strArray[1] = rawFillZeroString(strArray[1], 4) ?? '';
841
+ strArray[2] = rawFillZeroString(strArray[2], 4) ?? '';
842
+ strArray[3] = rawFillZeroString(strArray[3], 4) ?? '';
843
+ strArray[4] = rawFillZeroString(strArray[4], 12) ?? '';
844
+ if ('' === strArray[0] || '' === strArray[1] || '' === strArray[2] || '' === strArray[3] || '' === strArray[4]) {
845
+ return null;
846
+ }
847
+ // uuid full hex string
848
+ const fullString = strArray.join('');
849
+ if (!/^[0-9a-fA-F]{32}$/.test(fullString)) {
850
+ return null;
851
+ }
852
+ // convert to binary array
853
+ try {
854
+ return Buffer.from(fullString, 'hex');
855
+ }
856
+ catch {
857
+ return null;
858
+ }
859
+ };
860
+ //
861
+ // Converts a decimal or hexadecimal character string into a Buffer array(hexadecimal)
862
+ // with a specified number of bytes.
863
+ //
864
+ // strNumber: string for decimal or hexadecimal number
865
+ // base: radix(10 or 16)
866
+ // size: output Buffer array size
867
+ //
868
+ // result: Buffer array
869
+ //
870
+ const rawCvtNumberStringToBinBuffer = (strNumber, base, size) => {
871
+ if (!rawIsSafeString(strNumber)) {
872
+ return null;
873
+ }
874
+ if (16 != base && 10 != base) {
875
+ return null;
876
+ }
877
+ if (10 == base) {
878
+ // convert dec string to hex string
879
+ const tmpNumber = parseInt(strNumber, 10);
880
+ strNumber = tmpNumber.toString(16);
881
+ }
882
+ const matched = strNumber.match(/.{1,2}/g);
883
+ const uintarr = new Uint8Array((matched ?? []).map((val) => parseInt(val, 16)));
884
+ const binbuff = Buffer.alloc(size);
885
+ binbuff.fill(0);
886
+ if (size < uintarr.length) {
887
+ // If input number array length is larger than required length, fill bottom.
888
+ const diff_length = uintarr.length - size;
889
+ for (let cnt = uintarr.length; diff_length < cnt; --cnt) {
890
+ binbuff[cnt - 1 - diff_length] = uintarr[cnt - 1];
891
+ }
892
+ }
893
+ else {
894
+ // If required length is larger than input length, fill zero to top.
895
+ const diff_length = size - uintarr.length;
896
+ for (let cnt = size; 0 < cnt; --cnt) {
897
+ if ((cnt - 1) < diff_length) {
898
+ break;
899
+ }
900
+ binbuff[cnt - 1] = uintarr[cnt - 1 - diff_length];
901
+ }
902
+ }
903
+ return binbuff;
904
+ };
905
+ //
906
+ // Return result
907
+ // {
908
+ // hi_id: Buffer[16] for hi uuid
909
+ // low_id: Buffer[16] for low uuid
910
+ // base: Buffer[32] for base
911
+ // str_token: hex[32] string for token
912
+ // token: Buffer[32] for token
913
+ // }
914
+ //
915
+ const rawMakeToken256 = (hiUuid4, lowUuid4, base) => {
916
+ // hiUuid4[128] / lowUuid4[128]
917
+ if (!rawIsSafeEntity(hiUuid4) || !(Buffer.isBuffer(hiUuid4)) || 16 != hiUuid4.length ||
918
+ !rawIsSafeEntity(lowUuid4) || !(Buffer.isBuffer(lowUuid4)) || 16 != lowUuid4.length ||
919
+ !rawIsSafeEntity(base) || !(Buffer.isBuffer(base)) || 32 != base.length) {
920
+ return null;
921
+ }
922
+ const result = {
923
+ hi_id: hiUuid4,
924
+ low_id: lowUuid4,
925
+ base: base,
926
+ str_token: '',
927
+ token: Buffer.alloc(0)
928
+ };
929
+ // raw not crypted token[256]
930
+ const token = Buffer.alloc(32);
931
+ for (let cnt = 0; cnt < 32; ++cnt) {
932
+ if (cnt < 16) {
933
+ token[cnt] = result.base[cnt] ^ hiUuid4[cnt];
934
+ }
935
+ else {
936
+ token[cnt] = result.base[cnt] ^ lowUuid4[cnt - 16];
937
+ }
938
+ }
939
+ // sha256 token[256]
940
+ const cryptSha256 = crypto.createHash('sha256');
941
+ cryptSha256.update(token);
942
+ result.str_token = cryptSha256.digest('hex');
943
+ // sha256 binary token[256]
944
+ result.token = rawCvtNumberStringToBinBuffer(result.str_token, 16, 32) ?? Buffer.alloc(0);
945
+ return result;
946
+ };
947
+ //
948
+ // Return result
949
+ // {
950
+ // str_hi_id: hi uuid string
951
+ // hi_id: Buffer[16] for hi uuid
952
+ // str_low_id: low uuid string
953
+ // low_id: Buffer[16] for low uuid
954
+ // str_base: base string
955
+ // base: Buffer[32] for base
956
+ // str_token: hex[32] string for token
957
+ // token: Buffer[32] for token
958
+ // }
959
+ //
960
+ const rawMakeStringToken256 = (strHiUuid4, strLowUuid4, strBase) => {
961
+ if (!rawIsSafeString(strHiUuid4) || !rawIsSafeString(strLowUuid4)) {
962
+ return null;
963
+ }
964
+ const hiUuid4 = rawCvtStrToBinUuid4(strHiUuid4);
965
+ const lowUuid4 = rawCvtStrToBinUuid4(strLowUuid4);
966
+ if (null === hiUuid4 || null === lowUuid4) {
967
+ return null;
968
+ }
969
+ let base;
970
+ if (rawIsString(strBase)) {
971
+ // string base is specified as string, then convert to buffer[32]
972
+ base = rawCvtNumberStringToBinBuffer(strBase, 16, 32);
973
+ }
974
+ else if (rawIsSafeNumber(strBase)) {
975
+ // string base is specified as number, then convert to buffer[32]
976
+ base = rawCvtNumberStringToBinBuffer(String(strBase), 16, 32);
977
+ }
978
+ else { // null === strBase
979
+ // base is not specified, then it is made at here.
980
+ base = crypto.randomBytes(32); // base data is random value in buffer[32]
981
+ }
982
+ if (null === base) {
983
+ return null;
984
+ }
985
+ const binResult = rawMakeToken256(hiUuid4, lowUuid4, base);
986
+ if (null === binResult) {
987
+ return null;
988
+ }
989
+ const result = {
990
+ str_hi_id: strHiUuid4,
991
+ hi_id: binResult.hi_id,
992
+ str_low_id: strLowUuid4,
993
+ low_id: binResult.low_id,
994
+ str_base: base.toString('hex'),
995
+ base: binResult.base,
996
+ str_token: binResult.str_token,
997
+ token: binResult.token,
998
+ };
999
+ return result;
1000
+ };
1001
+ const rawCvtNumberStringToUuid4 = (strNumber, base) => {
1002
+ const bin_uuid4 = rawCvtNumberStringToBinBuffer(strNumber, base, 16); // UUID4 is 16bytes
1003
+ if (null == bin_uuid4) {
1004
+ return null;
1005
+ }
1006
+ return rawGetStrUuid4(bin_uuid4);
1007
+ };
1008
+ //---------------------------------------------------------
1009
+ // Utilities for Host/IP address
1010
+ //---------------------------------------------------------
1011
+ //
1012
+ // Get client ip address
1013
+ //
1014
+ // [NOTE]
1015
+ // If the server is behind of proxy, you have to set "trust proxy" to express app.
1016
+ // Then we get client ip address in X-Forwarded-for header from req.ip.
1017
+ //
1018
+ // If you do not use "trust proxy", you can get client ip by following:
1019
+ //
1020
+ // ip = (rawIsSafeEntity(req.headers) && rawIsSafeEntity(req.headers['x-forwarded-for'])) ? req.headers['x-forwarded-for'].split(',')[0] :
1021
+ // (rawIsSafeEntity(req.connection) && rawIsSafeString(req.connection.remoteAddress)) ? req.connection.remoteAddress :
1022
+ // (rawIsSafeEntity(req.connection) && rawIsSafeEntity(req.connection.socket) && rawIsSafeString(req.connection.socket.remoteAddress)) ? req.connection.socket.remoteAddress :
1023
+ // (rawIsSafeEntity(req.socket) && rawIsSafeString(req.socket.remoteAddress)) ? req.socket.remoteAddress :
1024
+ // '0.0.0.0';
1025
+ // ip = ip.split(':').slice(-1); //in case the ip returned in a format: "::ffff:xxx.xxx.xxx.xxx"
1026
+ //
1027
+ const rawGetClientIpAddress = (req) => {
1028
+ // If "trust proxy" is set, set client ip address to req.ip.
1029
+ let ip = (rawIsSafeEntity(req) && rawIsSafeString(req.ip)) ? (req.ip ?? null) : null;
1030
+ if (!rawIsSafeString(ip)) {
1031
+ ip = null;
1032
+ }
1033
+ else {
1034
+ // check format "::ffff:" for ipv4 on ipv6
1035
+ if ('::ffff:' === ip.substr(0, 7)) {
1036
+ ip = ip.substr(7);
1037
+ }
1038
+ }
1039
+ return ip;
1040
+ };
1041
+ const rawCompareRequestIpAddress = (req, ip) => {
1042
+ const req_ip = rawGetClientIpAddress(req);
1043
+ if (null === req_ip) {
1044
+ return false;
1045
+ }
1046
+ return (req_ip === ip);
1047
+ };
1048
+ //
1049
+ // Get hostname from ip address
1050
+ //
1051
+ // ip : ip address
1052
+ // callback : function(err message, result<string[]>)
1053
+ //
1054
+ const rawGetHostnameFromIpAddress = (ip, callback) => {
1055
+ if (!rawIsSafeString(ip)) {
1056
+ callback('ip address parameter is wrong', null);
1057
+ return;
1058
+ }
1059
+ dns.reverse(ip, (err, hosts) => {
1060
+ if (rawIsSafeEntity(err)) {
1061
+ callback('ip address(' + ip + ') is not convert hostname: ' + err.message, null);
1062
+ return;
1063
+ }
1064
+ if (!rawIsNotEmptyArray(hosts)) {
1065
+ callback('ip address(' + ip + ') is not convert hostname', null);
1066
+ return;
1067
+ }
1068
+ callback(null, hosts);
1069
+ });
1070
+ };
1071
+ //
1072
+ // Get ip address from hostname
1073
+ //
1074
+ // hostname : host name
1075
+ // callback : function(err message, result<string[]>)
1076
+ //
1077
+ const rawGetIpAddressFromHostname = (hostname, callback) => {
1078
+ if (!rawIsSafeString(hostname)) {
1079
+ callback('hostname parameter is wrong', null);
1080
+ return;
1081
+ }
1082
+ // try ipv4
1083
+ const _hostname4 = hostname;
1084
+ dns.resolve4(_hostname4, (err, ip4) => {
1085
+ if (rawIsSafeEntity(err) || !rawIsNotEmptyArray(ip4)) {
1086
+ // try ipv6
1087
+ const _hostname6 = _hostname4;
1088
+ dns.resolve6(_hostname6, (err, ip6) => {
1089
+ if (rawIsSafeEntity(err) || !rawIsNotEmptyArray(ip6)) {
1090
+ let strErrMsg = 'hostname(' + _hostname6 + ') is not convert ipv6 address : ';
1091
+ if (rawIsSafeEntity(err) && rawIsSafeString(err.message)) {
1092
+ strErrMsg += err.message;
1093
+ }
1094
+ callback(strErrMsg, null);
1095
+ return;
1096
+ }
1097
+ callback(null, ip6);
1098
+ });
1099
+ }
1100
+ callback(null, ip4);
1101
+ });
1102
+ };
1103
+ //
1104
+ // Complement ip address and hostname
1105
+ //
1106
+ // hostname : host name
1107
+ // ip : ip address
1108
+ // callback : function(err message, ip array[ip,...], hostname array[name,...])
1109
+ //
1110
+ const rawComplementHostnameIpAddress = (hostname, ip, callback) => {
1111
+ if (!rawIsSafeString(hostname) && !rawIsSafeString(ip)) {
1112
+ callback('hostname and ip parameter is wrong', null, null);
1113
+ return;
1114
+ }
1115
+ if (rawIsSafeString(hostname) && rawIsSafeString(ip)) {
1116
+ const ips = [ip];
1117
+ const hosts = [hostname];
1118
+ callback('hostname and ip parameter is wrong', ips, hosts);
1119
+ return;
1120
+ }
1121
+ if (rawIsSafeString(hostname)) {
1122
+ const _hostname = [hostname];
1123
+ rawGetIpAddressFromHostname(ip, (err, result) => {
1124
+ if (rawIsSafeEntity(err)) {
1125
+ callback(err, null, null);
1126
+ return;
1127
+ }
1128
+ callback(null, result, _hostname);
1129
+ });
1130
+ }
1131
+ else if (rawIsSafeString(ip)) {
1132
+ const _ips = [ip];
1133
+ rawGetHostnameFromIpAddress(ip, (err, result) => {
1134
+ if (rawIsSafeEntity(err)) {
1135
+ callback(err, null, null);
1136
+ return;
1137
+ }
1138
+ callback(null, _ips, result);
1139
+ });
1140
+ }
1141
+ };
1142
+ //
1143
+ // url parser with default port
1144
+ //
1145
+ const rawUrlParse = (strurl) => {
1146
+ const ep = url.parse(strurl);
1147
+ if (rawIsSafeEntity(ep) && (null === ep.port || !rawIsSafeEntity(ep.port) || isNaN(Number(ep.port)))) {
1148
+ // set default port
1149
+ if (rawIsSafeString(ep.protocol) && 'https:' === ep.protocol) {
1150
+ ep.port = String(443);
1151
+ }
1152
+ else {
1153
+ ep.port = String(80);
1154
+ }
1155
+ }
1156
+ return ep;
1157
+ };
1158
+ //
1159
+ // Check hostname/ip address
1160
+ //
1161
+ // host : hostname or ip address string
1162
+ //
1163
+ const simple_reg_ipv4 = /^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/;
1164
+ const simple_reg_ipv6 = /^(([0-9]|[a-f]|[A-F])*:)*([0-9]|[a-f]|[A-F])$/;
1165
+ const rawIsIpAddressString = (host) => {
1166
+ if (!rawIsSafeString(host)) {
1167
+ return false;
1168
+ }
1169
+ if (host.match(simple_reg_ipv4) || host.match(simple_reg_ipv6)) {
1170
+ return true;
1171
+ }
1172
+ return false;
1173
+ };
1174
+ //
1175
+ // Check URL
1176
+ //
1177
+ // Allow formatted as "http(s)://<host{:port}>{/{<path>}...}"
1178
+ //
1179
+ // Result matches by regex
1180
+ // matches.length 7
1181
+ // matches[0] input string(url)
1182
+ // matches[1] method string(http or https)
1183
+ // matches[2] FQDN string(domain name)
1184
+ // matches[3] port number starting with ':'(':xxxx'). if url does not have port, this value is ''(empty string)
1185
+ // matches[4] port number starting with ':'(':xxxx'). if url does not have port, this value is undefined
1186
+ // matches[5] url path and arguments string(string after port number). if url end of character is port number, this value is ''(empty string)
1187
+ // matches[6] url path and arguments string(string after port number). if url end of character is port number, this value is undefined
1188
+ //
1189
+ // Ex.)
1190
+ // Input url : 'https://abc.co.jp:8080/path?arg=value'
1191
+ // matches : [ 'https://abc.co.jp:8080/path?arg=value',
1192
+ // 'https',
1193
+ // 'abc.co.jp',
1194
+ // ':8080',
1195
+ // ':8080',
1196
+ // '/path?arg=value',
1197
+ // '/path?arg=value',
1198
+ // index: 0,
1199
+ // input: 'https://abc.co.jp:8080/path?arg=value'
1200
+ // ]
1201
+ //
1202
+ // Input url : 'https://abc.co.jp/'
1203
+ // matches : [ 'https://abc.co.jp/',
1204
+ // 'https',
1205
+ // 'abc.co.jp',
1206
+ // '',
1207
+ // undefined,
1208
+ // '',
1209
+ // undefined,
1210
+ // index: 0,
1211
+ // input: 'https://abc.co.jp/'
1212
+ // ]
1213
+ //
1214
+ const reg_url = /^(https?):\/\/([a-z|A-Z|0-9|$|%|&|(|)|-|=|~|^|||@|+|.|_]+)((:[1-9]\d*)?)((\/.*)*)$/;
1215
+ const rawIsSafeUrl = (strurl) => {
1216
+ if (!rawIsSafeString(strurl)) {
1217
+ return false;
1218
+ }
1219
+ if (null === strurl.match(reg_url)) {
1220
+ return false;
1221
+ }
1222
+ return true;
1223
+ };
1224
+ const rawParseUrl = (strurl) => {
1225
+ if (!rawIsSafeString(strurl)) {
1226
+ return null;
1227
+ }
1228
+ const matches = strurl.match(reg_url);
1229
+ if (null === matches || !rawIsNotEmptyArray(matches) || matches.length < 7) {
1230
+ return null;
1231
+ }
1232
+ const resobj = { https: false, host: '', path: '', port: 0 };
1233
+ resobj.https = rawCompareCaseString(matches[1], 'https');
1234
+ resobj.host = matches[2];
1235
+ resobj.path = matches[5];
1236
+ if (rawIsSafeString(matches[3]) && !isNaN(Number(matches[3].substr(1)))) {
1237
+ resobj.port = parseInt(matches[3].substr(1));
1238
+ }
1239
+ else {
1240
+ resobj.port = resobj.https ? 443 : 80;
1241
+ }
1242
+ return resobj;
1243
+ };
1244
+ const rawCheckFileExist = (file) => {
1245
+ if (!rawIsSafeString(file)) {
1246
+ return false;
1247
+ }
1248
+ try {
1249
+ fs.statSync(file);
1250
+ }
1251
+ catch {
1252
+ return false;
1253
+ }
1254
+ return true;
1255
+ };
1256
+ const rawReadFileContents = (file) => {
1257
+ if (!rawIsSafeString(file)) {
1258
+ return null;
1259
+ }
1260
+ if (!rawCheckFileExist(file)) {
1261
+ return null;
1262
+ }
1263
+ try {
1264
+ return fs.readFileSync(file).toString();
1265
+ }
1266
+ catch {
1267
+ return null;
1268
+ }
1269
+ };
1270
+ const rawCheckDir = (path) => {
1271
+ if (!rawIsSafeString(path)) {
1272
+ return false;
1273
+ }
1274
+ return fs.existsSync(path);
1275
+ };
1276
+ const rawCheckMakeDir = (path) => {
1277
+ if (!rawIsSafeString(path)) {
1278
+ return false;
1279
+ }
1280
+ if (rawCheckDir(path)) {
1281
+ return true;
1282
+ }
1283
+ try {
1284
+ fs.mkdirSync(path);
1285
+ }
1286
+ catch {
1287
+ return false;
1288
+ }
1289
+ return true;
1290
+ };
1291
+ //---------------------------------------------------------
1292
+ // Utilities for dnamic import
1293
+ //---------------------------------------------------------
1294
+ const rawTryLoadModule = async (filepath) => {
1295
+ const candidates = filepath.endsWith('.js') ? [filepath] : [filepath, (filepath + '.js')];
1296
+ const errors = [];
1297
+ for (const cand of candidates) {
1298
+ try {
1299
+ const modRaw = (await import(cand));
1300
+ if (rawIsPlainObject(modRaw)) {
1301
+ const defaultExport = modRaw.default || modRaw;
1302
+ if (rawIsPlainObject(defaultExport)) {
1303
+ const keys = Object.keys(defaultExport);
1304
+ if (0 < keys.length) {
1305
+ const firstKey = keys[0];
1306
+ return defaultExport[firstKey];
1307
+ }
1308
+ else {
1309
+ return defaultExport;
1310
+ }
1311
+ }
1312
+ else {
1313
+ return defaultExport;
1314
+ }
1315
+ }
1316
+ else {
1317
+ return modRaw;
1318
+ }
1319
+ }
1320
+ catch (error) {
1321
+ errors.push(cand + ' -> ' + JSON.stringify(error));
1322
+ }
1323
+ }
1324
+ console.debug('import failed : ', JSON.stringify(errors));
1325
+ return null;
1326
+ };
1327
+ //---------------------------------------------------------
1328
+ // Utilities for variables defined in type.ts
1329
+ //---------------------------------------------------------
1330
+ const rawIsValTypeTokenSeed = (val) => {
1331
+ if (!rawIsPlainObject(val)) {
1332
+ return false;
1333
+ }
1334
+ const _obj = val;
1335
+ const _isString = (key) => rawIsString(_obj[key]);
1336
+ const _isStringOrNull = (key) => null === _obj[key] || rawIsString(_obj[key]);
1337
+ const _isFiniteNumber = (key) => rawIsSafeNumber(_obj[key]);
1338
+ return (_isString('publisher') &&
1339
+ _isString('userexid') &&
1340
+ _isString('date') &&
1341
+ _isString('expire') &&
1342
+ _isString('creator') &&
1343
+ _isString('base') &&
1344
+ _isStringOrNull('user') &&
1345
+ _isStringOrNull('ip') &&
1346
+ _isStringOrNull('hostname') &&
1347
+ _isFiniteNumber('port') &&
1348
+ _isStringOrNull('cuk') &&
1349
+ _isStringOrNull('extra') &&
1350
+ _isStringOrNull('tenant'));
1351
+ };
1352
+ const rawIsValTypeRoleInfo = (val) => {
1353
+ if (!rawIsPlainObject(val)) {
1354
+ return false;
1355
+ }
1356
+ if ((undefined !== val.role && !rawIsString(val.role)) ||
1357
+ (undefined !== val.token && !rawIsString(val.token))) {
1358
+ return false;
1359
+ }
1360
+ for (const [, value] of Object.entries(val)) {
1361
+ if (!rawIsValTypeAll(value)) {
1362
+ return false;
1363
+ }
1364
+ }
1365
+ return true;
1366
+ };
1367
+ //---------------------------------------------------------
1368
+ // Exports
1369
+ //---------------------------------------------------------
1370
+ exports.k2hr3ppiutil = {
1371
+ isSafeEntity: rawIsSafeEntity,
1372
+ isString: rawIsString,
1373
+ isSafeString: rawIsSafeString,
1374
+ isPlainObject: rawIsPlainObject,
1375
+ isValTypeAllObject: rawIsValTypeAllObject,
1376
+ isValTypeAll: rawIsValTypeAll,
1377
+ isFunction: rawIsFunction,
1378
+ isBoolean: rawIsBoolean,
1379
+ isSafeNumber: rawIsSafeNumber,
1380
+ isSafeNumeric: rawIsSafeNumeric,
1381
+ cvtToNumber: rawCvtToNumber,
1382
+ compareCaseString: rawCompareCaseString,
1383
+ isArray: rawIsArray,
1384
+ isStringArray: rawIsStringArray,
1385
+ isString2DArray: rawIsString2DArray,
1386
+ hasPartString: rawHasPartString,
1387
+ getSafeString: rawGetSafeString,
1388
+ checkSimpleJSON: rawCheckSimpleJSON,
1389
+ parseJSON: rawParseJSON,
1390
+ isNotEmptyArray: rawIsNotEmptyArray,
1391
+ getSafeArray: rawGetSafeArray,
1392
+ getSafeStringArray: rawGetSafeStringArray,
1393
+ findStringInArray: rawFindStringInArray,
1394
+ addStringToArray: rawAddStringToArray,
1395
+ tryAddStringToArray: rawTryAddStringToArray,
1396
+ removeStringFromArray: rawRemoveStringFromArray,
1397
+ compareArray: rawCompareArray,
1398
+ mergeArray: rawMergeArray,
1399
+ getDeletingDifferenceArray: (basearr, newarr) => rawGetDiffArray(basearr, newarr, true),
1400
+ getAddingDifferenceArray: (basearr, newarr) => rawGetDiffArray(basearr, newarr, false),
1401
+ mergeObjects: rawMergeObjects,
1402
+ mergeValTypeAllObject: rawMergeValTypeAllObject,
1403
+ getUnixtime: rawConvertUnixtime,
1404
+ calcExpire: rawCalcExpire,
1405
+ isExpired: rawIsExpired,
1406
+ convertISOStringToUnixtime: rawConvertISOStringToUnixtime,
1407
+ getExpireUnixtime: rawGetExpireUnixtime,
1408
+ getExpireUnixtimeFromISOStrings: rawGetExpireUnixtimeFromISOStrings,
1409
+ expandHierarchy: rawExpandHierarchy,
1410
+ getParentKey: rawGetParentKey,
1411
+ getParentPath: rawGetParentPath,
1412
+ getNormalizeParameter: rawGetNormalizeParameter,
1413
+ getBinUuid4: rawGetBinUuid4,
1414
+ getStrUuid4: rawGetStrUuid4,
1415
+ isSafeStrUuid4: rawIsSafeStrUuid4,
1416
+ cvtStrToBinUuid4: rawCvtStrToBinUuid4,
1417
+ cvtNumberStringToBinBuffer: rawCvtNumberStringToBinBuffer,
1418
+ makeToken256: rawMakeToken256,
1419
+ makeStringToken256: rawMakeStringToken256,
1420
+ cvtNumberStringToUuid4: rawCvtNumberStringToUuid4,
1421
+ getClientIpAddress: rawGetClientIpAddress,
1422
+ compareRequestIpAddress: rawCompareRequestIpAddress,
1423
+ complementHostnameIpAddress: rawComplementHostnameIpAddress,
1424
+ urlParse: rawUrlParse,
1425
+ isIpAddressString: rawIsIpAddressString,
1426
+ isSafeUrl: rawIsSafeUrl,
1427
+ parseUrl: rawParseUrl,
1428
+ checkFileExist: rawCheckFileExist,
1429
+ readFileContents: rawReadFileContents,
1430
+ checkDir: rawCheckDir,
1431
+ checkMakeDir: rawCheckMakeDir,
1432
+ tryLoadModule: rawTryLoadModule,
1433
+ isValTypeTokenSeed: rawIsValTypeTokenSeed,
1434
+ isValTypeRoleInfo: rawIsValTypeRoleInfo
1435
+ };
1436
+ exports.default = exports.k2hr3ppiutil;
1437
+ /*
1438
+ * Local variables:
1439
+ * tab-width: 4
1440
+ * c-basic-offset: 4
1441
+ * End:
1442
+ * vim600: noexpandtab sw=4 ts=4 fdm=marker
1443
+ * vim<600: noexpandtab sw=4 ts=4
1444
+ */