fa-mcp-sdk 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +283 -0
  3. package/dist/core/_types_/types.d.ts +67 -0
  4. package/dist/core/_types_/types.d.ts.map +1 -0
  5. package/dist/core/_types_/types.js +2 -0
  6. package/dist/core/_types_/types.js.map +1 -0
  7. package/dist/core/bootstrap/dotenv.d.ts +3 -0
  8. package/dist/core/bootstrap/dotenv.d.ts.map +1 -0
  9. package/dist/core/bootstrap/dotenv.js +3 -0
  10. package/dist/core/bootstrap/dotenv.js.map +1 -0
  11. package/dist/core/bootstrap/init-config.d.ts +11 -0
  12. package/dist/core/bootstrap/init-config.d.ts.map +1 -0
  13. package/dist/core/bootstrap/init-config.js +52 -0
  14. package/dist/core/bootstrap/init-config.js.map +1 -0
  15. package/dist/core/bootstrap/startup-info.d.ts +6 -0
  16. package/dist/core/bootstrap/startup-info.d.ts.map +1 -0
  17. package/dist/core/bootstrap/startup-info.js +43 -0
  18. package/dist/core/bootstrap/startup-info.js.map +1 -0
  19. package/dist/core/constants.d.ts +2 -0
  20. package/dist/core/constants.d.ts.map +1 -0
  21. package/dist/core/constants.js +2 -0
  22. package/dist/core/constants.js.map +1 -0
  23. package/dist/core/consul/access-points-updater.d.ts +5 -0
  24. package/dist/core/consul/access-points-updater.d.ts.map +1 -0
  25. package/dist/core/consul/access-points-updater.js +11 -0
  26. package/dist/core/consul/access-points-updater.js.map +1 -0
  27. package/dist/core/consul/deregister.d.ts +2 -0
  28. package/dist/core/consul/deregister.d.ts.map +1 -0
  29. package/dist/core/consul/deregister.js +21 -0
  30. package/dist/core/consul/deregister.js.map +1 -0
  31. package/dist/core/consul/get-consul-api.d.ts +2 -0
  32. package/dist/core/consul/get-consul-api.d.ts.map +1 -0
  33. package/dist/core/consul/get-consul-api.js +18 -0
  34. package/dist/core/consul/get-consul-api.js.map +1 -0
  35. package/dist/core/consul/register.d.ts +2 -0
  36. package/dist/core/consul/register.d.ts.map +1 -0
  37. package/dist/core/consul/register.js +6 -0
  38. package/dist/core/consul/register.js.map +1 -0
  39. package/dist/core/db/pg-db.d.ts +50 -0
  40. package/dist/core/db/pg-db.d.ts.map +1 -0
  41. package/dist/core/db/pg-db.js +89 -0
  42. package/dist/core/db/pg-db.js.map +1 -0
  43. package/dist/core/debug.d.ts +5 -0
  44. package/dist/core/debug.d.ts.map +1 -0
  45. package/dist/core/debug.js +32 -0
  46. package/dist/core/debug.js.map +1 -0
  47. package/dist/core/ee.d.ts +3 -0
  48. package/dist/core/ee.d.ts.map +1 -0
  49. package/dist/core/ee.js +4 -0
  50. package/dist/core/ee.js.map +1 -0
  51. package/dist/core/errors/BaseMcpError.d.ts +19 -0
  52. package/dist/core/errors/BaseMcpError.d.ts.map +1 -0
  53. package/dist/core/errors/BaseMcpError.js +47 -0
  54. package/dist/core/errors/BaseMcpError.js.map +1 -0
  55. package/dist/core/errors/ValidationError.d.ts +5 -0
  56. package/dist/core/errors/ValidationError.d.ts.map +1 -0
  57. package/dist/core/errors/ValidationError.js +7 -0
  58. package/dist/core/errors/ValidationError.js.map +1 -0
  59. package/dist/core/errors/errors.d.ts +24 -0
  60. package/dist/core/errors/errors.d.ts.map +1 -0
  61. package/dist/core/errors/errors.js +49 -0
  62. package/dist/core/errors/errors.js.map +1 -0
  63. package/dist/core/index.d.ts +19 -0
  64. package/dist/core/index.d.ts.map +1 -0
  65. package/dist/core/index.js +16 -0
  66. package/dist/core/index.js.map +1 -0
  67. package/dist/core/init-mcp-server.d.ts +8 -0
  68. package/dist/core/init-mcp-server.d.ts.map +1 -0
  69. package/dist/core/init-mcp-server.js +101 -0
  70. package/dist/core/init-mcp-server.js.map +1 -0
  71. package/dist/core/logger.d.ts +6 -0
  72. package/dist/core/logger.d.ts.map +1 -0
  73. package/dist/core/logger.js +53 -0
  74. package/dist/core/logger.js.map +1 -0
  75. package/dist/core/mcp/create-mcp-server.d.ts +6 -0
  76. package/dist/core/mcp/create-mcp-server.d.ts.map +1 -0
  77. package/dist/core/mcp/create-mcp-server.js +44 -0
  78. package/dist/core/mcp/create-mcp-server.js.map +1 -0
  79. package/dist/core/mcp/prompts.d.ts +10 -0
  80. package/dist/core/mcp/prompts.d.ts.map +1 -0
  81. package/dist/core/mcp/prompts.js +56 -0
  82. package/dist/core/mcp/prompts.js.map +1 -0
  83. package/dist/core/mcp/resources.d.ts +14 -0
  84. package/dist/core/mcp/resources.d.ts.map +1 -0
  85. package/dist/core/mcp/resources.js +72 -0
  86. package/dist/core/mcp/resources.js.map +1 -0
  87. package/dist/core/mcp/server-stdio.d.ts +5 -0
  88. package/dist/core/mcp/server-stdio.d.ts.map +1 -0
  89. package/dist/core/mcp/server-stdio.js +13 -0
  90. package/dist/core/mcp/server-stdio.js.map +1 -0
  91. package/dist/core/token/gen-token-app/gen-token-server.d.ts +2 -0
  92. package/dist/core/token/gen-token-app/gen-token-server.d.ts.map +1 -0
  93. package/dist/core/token/gen-token-app/gen-token-server.js +115 -0
  94. package/dist/core/token/gen-token-app/gen-token-server.js.map +1 -0
  95. package/dist/core/token/gen-token-app/html.d.ts +2 -0
  96. package/dist/core/token/gen-token-app/html.d.ts.map +1 -0
  97. package/dist/core/token/gen-token-app/html.js +500 -0
  98. package/dist/core/token/gen-token-app/html.js.map +1 -0
  99. package/dist/core/token/i-token.d.ts +13 -0
  100. package/dist/core/token/i-token.d.ts.map +1 -0
  101. package/dist/core/token/i-token.js +2 -0
  102. package/dist/core/token/i-token.js.map +1 -0
  103. package/dist/core/token/token-core.d.ts +24 -0
  104. package/dist/core/token/token-core.d.ts.map +1 -0
  105. package/dist/core/token/token-core.js +130 -0
  106. package/dist/core/token/token-core.js.map +1 -0
  107. package/dist/core/token/token.d.ts +17 -0
  108. package/dist/core/token/token.d.ts.map +1 -0
  109. package/dist/core/token/token.js +62 -0
  110. package/dist/core/token/token.js.map +1 -0
  111. package/dist/core/utils/formatToolResult.d.ts +7 -0
  112. package/dist/core/utils/formatToolResult.d.ts.map +1 -0
  113. package/dist/core/utils/formatToolResult.js +68 -0
  114. package/dist/core/utils/formatToolResult.js.map +1 -0
  115. package/dist/core/utils/rate-limit.d.ts +17 -0
  116. package/dist/core/utils/rate-limit.d.ts.map +1 -0
  117. package/dist/core/utils/rate-limit.js +56 -0
  118. package/dist/core/utils/rate-limit.js.map +1 -0
  119. package/dist/core/utils/utils.d.ts +6 -0
  120. package/dist/core/utils/utils.d.ts.map +1 -0
  121. package/dist/core/utils/utils.js +12 -0
  122. package/dist/core/utils/utils.js.map +1 -0
  123. package/dist/core/web/about-page/css.d.ts +2 -0
  124. package/dist/core/web/about-page/css.d.ts.map +1 -0
  125. package/dist/core/web/about-page/css.js +534 -0
  126. package/dist/core/web/about-page/css.js.map +1 -0
  127. package/dist/core/web/about-page/render.d.ts +2 -0
  128. package/dist/core/web/about-page/render.d.ts.map +1 -0
  129. package/dist/core/web/about-page/render.js +679 -0
  130. package/dist/core/web/about-page/render.js.map +1 -0
  131. package/dist/core/web/cors.d.ts +5 -0
  132. package/dist/core/web/cors.d.ts.map +1 -0
  133. package/dist/core/web/cors.js +22 -0
  134. package/dist/core/web/cors.js.map +1 -0
  135. package/dist/core/web/favicon-svg.d.ts +7 -0
  136. package/dist/core/web/favicon-svg.d.ts.map +1 -0
  137. package/dist/core/web/favicon-svg.js +44 -0
  138. package/dist/core/web/favicon-svg.js.map +1 -0
  139. package/dist/core/web/server-http.d.ts +5 -0
  140. package/dist/core/web/server-http.d.ts.map +1 -0
  141. package/dist/core/web/server-http.js +275 -0
  142. package/dist/core/web/server-http.js.map +1 -0
  143. package/package.json +88 -0
@@ -0,0 +1,500 @@
1
+ export const getHTMLPage = () => `<!DOCTYPE html>
2
+ <html lang='ru'>
3
+ <head>
4
+ <meta charset='UTF-8'>
5
+ <meta name='viewport' content='width=device-width, initial-scale=1.0'>
6
+ <title>Token Generator & Validator</title>
7
+ <style>
8
+ * {
9
+ box-sizing: border-box;
10
+ margin: 0;
11
+ padding: 0;
12
+ }
13
+
14
+ body {
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ padding: 20px;
22
+ }
23
+
24
+ .container {
25
+ background: white;
26
+ border-radius: 20px;
27
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
28
+ padding: 30px;
29
+ width: 100%;
30
+ max-width: 800px;
31
+ }
32
+
33
+ .tab-container {
34
+ margin-bottom: 30px;
35
+ }
36
+
37
+ .tabs {
38
+ display: flex;
39
+ border-bottom: 2px solid #f0f0f0;
40
+ margin-bottom: 20px;
41
+ }
42
+
43
+ .tab {
44
+ background: none;
45
+ border: none;
46
+ padding: 15px 25px;
47
+ cursor: pointer;
48
+ font-size: 16px;
49
+ font-weight: 500;
50
+ color: #666;
51
+ border-bottom: 2px solid transparent;
52
+ transition: all 0.3s ease;
53
+ }
54
+
55
+ .tab.active {
56
+ color: #667eea;
57
+ border-bottom-color: #667eea;
58
+ }
59
+
60
+ .tab:hover {
61
+ background: #f9f9f9;
62
+ }
63
+
64
+ .tab-content {
65
+ display: none;
66
+ }
67
+
68
+ .tab-content.active {
69
+ display: block;
70
+ }
71
+
72
+ .form-group {
73
+ margin-bottom: 20px;
74
+ }
75
+
76
+ .form-row {
77
+ display: flex;
78
+ gap: 10px;
79
+ align-items: center;
80
+ }
81
+
82
+ label {
83
+ display: block;
84
+ margin-bottom: 5px;
85
+ font-weight: 500;
86
+ color: #333;
87
+ }
88
+
89
+ input, select, textarea {
90
+ width: 100%;
91
+ padding: 12px;
92
+ border: 2px solid #e0e0e0;
93
+ border-radius: 8px;
94
+ font-size: 14px;
95
+ transition: border-color 0.3s ease;
96
+ }
97
+
98
+ input:focus, select:focus, textarea:focus {
99
+ outline: none;
100
+ border-color: #667eea;
101
+ }
102
+
103
+ .time-input {
104
+ flex: 1;
105
+ }
106
+
107
+ .time-unit {
108
+ flex: 0 0 120px;
109
+ }
110
+
111
+ .key-value-pair {
112
+ display: flex;
113
+ gap: 10px;
114
+ margin-bottom: 10px;
115
+ align-items: center;
116
+ }
117
+
118
+ .key-value-pair input {
119
+ margin-bottom: 0;
120
+ }
121
+
122
+ .key-value-pair input[name="keys"] {
123
+ width: 180px;
124
+ flex-shrink: 0;
125
+ }
126
+
127
+ .key-value-pair input[name="values"] {
128
+ flex: 1;
129
+ }
130
+
131
+ .remove-btn {
132
+ background: #ffffff;
133
+ color: #ff0000;
134
+ border: 1px solid #ffb7b7;
135
+ border-radius: 50%;
136
+ width: 36px;
137
+ height: 36px;
138
+ cursor: pointer;
139
+ font-size: 24px;
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ transition: background 0.3s ease;
144
+ }
145
+
146
+ .remove-btn:hover {
147
+ background: #ff3838;
148
+ }
149
+
150
+ .add-btn {
151
+ background: #2ed573;
152
+ color: white;
153
+ border: none;
154
+ border-radius: 50%;
155
+ width: 40px;
156
+ height: 40px;
157
+ cursor: pointer;
158
+ font-size: 20px;
159
+ display: flex;
160
+ align-items: center;
161
+ justify-content: center;
162
+ margin: 10px auto;
163
+ transition: background 0.3s ease;
164
+ }
165
+
166
+ .add-btn:hover {
167
+ background: #26d068;
168
+ }
169
+
170
+ .btn {
171
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
172
+ color: white;
173
+ border: none;
174
+ padding: 15px 30px;
175
+ border-radius: 10px;
176
+ font-size: 16px;
177
+ font-weight: 500;
178
+ cursor: pointer;
179
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
180
+ width: 100%;
181
+ margin-bottom: 20px;
182
+ }
183
+
184
+ .btn:hover {
185
+ transform: translateY(-2px);
186
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
187
+ }
188
+
189
+ .btn:active {
190
+ transform: translateY(0);
191
+ }
192
+
193
+ .copy-btn {
194
+ background: #5352ed;
195
+ padding: 10px 20px;
196
+ font-size: 14px;
197
+ width: auto;
198
+ margin: 10px 0 0 0;
199
+ }
200
+
201
+ .result {
202
+ margin-top: 20px;
203
+ padding: 20px;
204
+ border-radius: 10px;
205
+ font-family: 'Courier New', monospace;
206
+ }
207
+
208
+ .result.success {
209
+ background: #d4edda;
210
+ color: #155724;
211
+ border: 1px solid #c3e6cb;
212
+ }
213
+
214
+ .result.error {
215
+ background: #f8d7da;
216
+ color: #721c24;
217
+ border: 1px solid #f5c6cb;
218
+ }
219
+
220
+ .token-output {
221
+ background: #f8f9fa;
222
+ border: 2px solid #e9ecef;
223
+ border-radius: 8px;
224
+ padding: 15px;
225
+ font-family: 'Courier New', monospace;
226
+ font-size: 12px;
227
+ line-height: 1.4;
228
+ word-break: break-all;
229
+ min-height: 100px;
230
+ resize: vertical;
231
+ }
232
+
233
+ .token-info {
234
+ background: #e8f5e8;
235
+ border: 1px solid #d4edda;
236
+ border-radius: 8px;
237
+ padding: 15px;
238
+ margin-top: 15px;
239
+ }
240
+
241
+ .token-info h4 {
242
+ margin-bottom: 10px;
243
+ color: #155724;
244
+ }
245
+
246
+ .token-info p {
247
+ margin: 5px 0;
248
+ font-family: 'Courier New', monospace;
249
+ font-size: 14px;
250
+ }
251
+ </style>
252
+ </head>
253
+ <body>
254
+ <div class="container">
255
+ <div class="tab-container">
256
+ <div class="tabs">
257
+ <button class="tab active" onclick="switchTab('generate')">Token generation</button>
258
+ <button class="tab" onclick="switchTab('validate')">Token validation</button>
259
+ </div>
260
+
261
+ <!-- Token generation -->
262
+ <div id="generate" class="tab-content active">
263
+ <form id="generateForm">
264
+ <div class="form-group">
265
+ <div class="form-row" style="gap: 20px;">
266
+ <div style="flex: 1;">
267
+ <label for="tokenUser">Who is the token issued to:</label>
268
+ <input type="text" id="tokenUser" name="user" required>
269
+ </div>
270
+ <div style="flex: 1;">
271
+ <label>For how long:</label>
272
+ <div class="form-row">
273
+ <input type="number" id="timeValue" name="timeValue" class="time-input" min="1" required>
274
+ <select id="timeUnit" name="timeUnit" class="time-unit">
275
+ <option value="minutes">minutes</option>
276
+ <option value="hours">hours</option>
277
+ <option value="days" selected>days</option>
278
+ <option value="months">months</option>
279
+ <option value="years">years</option>
280
+ </select>
281
+ </div>
282
+ </div>
283
+ </div>
284
+ </div>
285
+ <div class="form-group">
286
+ <label>Additional data (key-value):</label>
287
+ <div id="keyValuePairs"></div>
288
+ <button type="button" class="add-btn" onclick="addKeyValuePair()">+</button>
289
+ </div>
290
+ <button type="submit" class="btn">Generate a token</button>
291
+ </form>
292
+ <div id="generateResult"></div>
293
+ </div>
294
+
295
+ <!-- Token validation -->
296
+ <div id="validate" class="tab-content">
297
+ <form id="validateForm">
298
+ <div class="form-group">
299
+ <label for="tokenInput">Enter the token for verification:</label>
300
+ <textarea id="tokenInput" name="token" rows="4" required></textarea>
301
+ </div>
302
+ <button type="submit" class="btn">Check Token</button>
303
+ </form>
304
+ <div id="validateResult"></div>
305
+ </div>
306
+ </div>
307
+ </div>
308
+
309
+ <script>
310
+ let keyValuePairCount = 0;
311
+
312
+ function switchTab (tabName) {
313
+ document.querySelectorAll('.tab-content').forEach(content => {
314
+ content.classList.remove('active');
315
+ });
316
+ document.querySelectorAll('.tab').forEach(tab => {
317
+ tab.classList.remove('active');
318
+ });
319
+ document.getElementById(tabName).classList.add('active');
320
+ event.target.classList.add('active');
321
+ }
322
+
323
+ function addKeyValuePair (key = '', value = '', readonly = false, placeholder = 'Value') {
324
+ if (keyValuePairCount >= 15) {
325
+ alert('Maximum of 15 key-value pairs');
326
+ return;
327
+ }
328
+ const container = document.getElementById('keyValuePairs');
329
+ const pairDiv = document.createElement('div');
330
+ pairDiv.className = 'key-value-pair';
331
+
332
+ const keyInput = readonly ?
333
+ '<input type="text" placeholder="Key" name="keys" value="' + key + '" readonly style="background-color: #f8f9fa;">' :
334
+ '<input type="text" placeholder="Key" name="keys" value="' + key + '">';
335
+
336
+ const valueInput = '<input type="text" placeholder="' + placeholder + '" name="values" value="' + value + '">';
337
+
338
+ pairDiv.innerHTML = keyInput + valueInput +
339
+ '<button type="button" class="remove-btn" onclick="removeKeyValuePair(this)">×</button>';
340
+ container.appendChild(pairDiv);
341
+ keyValuePairCount++;
342
+ }
343
+
344
+ function removeKeyValuePair (button) {
345
+ button.parentElement.remove();
346
+ keyValuePairCount--;
347
+ }
348
+
349
+ function copyToClipboard (text) {
350
+ navigator.clipboard.writeText(text).then(() => {
351
+ alert('Token copied to clipboard!');
352
+ });
353
+ }
354
+
355
+ function formatTime (ms) {
356
+ const seconds = Math.floor(ms / 1000);
357
+ const minutes = Math.floor(seconds / 60);
358
+ const hours = Math.floor(minutes / 60);
359
+ const days = Math.floor(hours / 24);
360
+
361
+ if (days > 0) return days + ' d. ' + (hours % 24) + ' h.';
362
+ if (hours > 0) return hours + ' h. ' + (minutes % 60) + ' min.';
363
+ if (minutes > 0) return minutes + ' min.';
364
+ return seconds + ' s.';
365
+ }
366
+
367
+ // Processing the Generation Form
368
+ document.getElementById('generateForm').addEventListener('submit', async (e) => {
369
+ e.preventDefault();
370
+
371
+ const formData = new FormData(e.target);
372
+ const keys = formData.getAll('keys').filter(k => k.trim());
373
+ const values = formData.getAll('values').filter(v => v.trim());
374
+
375
+ const payload = {};
376
+ for (let i = 0; i < keys.length; i++) {
377
+ if (keys[i] && values[i]) {
378
+ payload[keys[i]] = values[i];
379
+ }
380
+ }
381
+
382
+ const requestData = {
383
+ user: formData.get('user'),
384
+ timeValue: parseInt(formData.get('timeValue')),
385
+ timeUnit: formData.get('timeUnit'),
386
+ payload: payload,
387
+ };
388
+
389
+ try {
390
+ const response = await fetch('/api/generate-token', {
391
+ method: 'POST',
392
+ headers: { 'Content-Type': 'application/json' },
393
+ body: JSON.stringify(requestData),
394
+ });
395
+
396
+ const result = await response.json();
397
+ const resultDiv = document.getElementById('generateResult');
398
+
399
+ if (result.success) {
400
+ resultDiv.innerHTML =
401
+ '<div class="result success">' +
402
+ '<strong>The token has been successfully created!</strong><br>' +
403
+ '<div class="token-output">' + result.token + '</div>' +
404
+ '<button class="copy-btn" onclick="copyToClipboard(\\'' + result.token + '\\')">Copy Token</button>' +
405
+ '</div>';
406
+ } else {
407
+ resultDiv.innerHTML =
408
+ '<div class="result error">' +
409
+ '<strong>Error:</strong> ' + result.error +
410
+ '</div>';
411
+ }
412
+ } catch (error) {
413
+ document.getElementById('generateResult').innerHTML =
414
+ '<div class="result error">' +
415
+ '<strong>Error:</strong> ' + error.message +
416
+ '</div>';
417
+ }
418
+ });
419
+
420
+ // Processing the Verification Form
421
+ document.getElementById('validateForm').addEventListener('submit', async (e) => {
422
+ e.preventDefault();
423
+
424
+ const formData = new FormData(e.target);
425
+ const token = formData.get('token').trim();
426
+
427
+ try {
428
+ const response = await fetch('/api/validate-token', {
429
+ method: 'POST',
430
+ headers: { 'Content-Type': 'application/json' },
431
+ body: JSON.stringify({ token }),
432
+ });
433
+
434
+ const result = await response.json();
435
+ const resultDiv = document.getElementById('validateResult');
436
+
437
+ if (result.success) {
438
+ const remainingTime = result.payload.expire - Date.now();
439
+ const payloadKeys = Object.keys(result.payload).filter(k => k !== 'user' && k !== 'expire');
440
+
441
+ let payloadHtml = '';
442
+ if (payloadKeys.length > 0) {
443
+ payloadHtml = '<h4>Additional data:</h4>';
444
+ payloadKeys.forEach(key => {
445
+ payloadHtml += '<p><strong>' + key + ':</strong> ' + result.payload[key] + '</p>';
446
+ });
447
+ }
448
+
449
+ resultDiv.innerHTML =
450
+ '<div class="result success">' +
451
+ '<strong>The token is valid!</strong>' +
452
+ '<div class="token-info">' +
453
+ '<h4>Token Information:</h4>' +
454
+ '<p><strong>User:</strong> ' + result.payload.user + '</p>' +
455
+ '<p><strong>Time remaining:</strong> ' + formatTime(remainingTime) + '</p>' +
456
+ '<p><strong>Expires:</strong> ' + new Date(result.payload.expire).toLocaleString('ru-RU') + '</p>' +
457
+ payloadHtml +
458
+ '</div>' +
459
+ '</div>';
460
+ } else {
461
+ resultDiv.innerHTML =
462
+ '<div class="result error">' +
463
+ '<strong>Token invalid!</strong><br>' +
464
+ 'Reason: ' + result.error +
465
+ '</div>';
466
+ }
467
+ } catch (error) {
468
+ document.getElementById('validateResult').innerHTML =
469
+ '<div class="result error">' +
470
+ '<strong>Error:</strong> ' + error.message +
471
+ '</div>';
472
+ }
473
+ });
474
+
475
+ // Function to initialize the form
476
+ async function initializeForm () {
477
+ try {
478
+ // Getting information about the service
479
+ const response = await fetch('/api/service-info');
480
+ const data = await response.json();
481
+ const serviceName = data.serviceName;
482
+
483
+ // Adding a pre-filled pair serviceName
484
+ addKeyValuePair('service', serviceName, true);
485
+ addKeyValuePair('issue', '', true, 'Reqoest for the issuance of a token');
486
+
487
+ } catch (error) {
488
+ console.error('Error loading service info:', error);
489
+ }
490
+ // Add one empty pair for the user
491
+ addKeyValuePair();
492
+ }
493
+
494
+ // Initialization on page load
495
+ initializeForm();
496
+ </script>
497
+ </body>
498
+ </html>
499
+ `;
500
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../../../src/core/token/gen-token-app/html.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,GAAW,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkfxC,CAAC"}
@@ -0,0 +1,13 @@
1
+ export type TTokenType = 'permanent' | 'JWT';
2
+ export interface ITokenPayload {
3
+ user: string;
4
+ expire: number;
5
+ [key: string]: any;
6
+ }
7
+ export interface ICheckTokenResult {
8
+ inTokenType?: TTokenType;
9
+ payload?: ITokenPayload;
10
+ errorReason?: string;
11
+ isTokenDecrypted?: boolean;
12
+ }
13
+ //# sourceMappingURL=i-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i-token.d.ts","sourceRoot":"","sources":["../../../src/core/token/i-token.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,UAAU,CAAA;IACxB,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=i-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i-token.js","sourceRoot":"","sources":["../../../src/core/token/i-token.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { ICheckTokenResult } from './i-token.js';
2
+ export declare const tokenRE: RegExp;
3
+ /**
4
+ * Encrypts the transmitted text with a symmetric key taken from the config
5
+ */
6
+ export declare const encrypt: (text: string) => string;
7
+ /**
8
+ * Decrypts the transmitted text with a symmetric key taken from the config
9
+ */
10
+ export declare const decrypt: (encryptedStr: string) => string;
11
+ /**
12
+ * Creates a token by encrypting the username and expiration time.
13
+ * To determine the expiration time in the JB form script, at the beginning of the token
14
+ * deprecation timestamp is added
15
+ */
16
+ export declare const generateToken: (user: string, liveTimeSec: number, payload?: any) => string;
17
+ /**
18
+ * Checks the validity of the token:
19
+ * - Token to be decrypted
20
+ * - the obsolescence time must not be expired
21
+ * - If a user is transferred, it must match
22
+ */
23
+ export declare const checkToken: (token: string, expectedUser?: string) => ICheckTokenResult;
24
+ //# sourceMappingURL=token-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-core.d.ts","sourceRoot":"","sources":["../../../src/core/token/token-core.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAiB,MAAM,cAAc,CAAC;AAkBhE,eAAO,MAAM,OAAO,QAAmC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,KAAG,MAStC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,GAAI,cAAc,MAAM,WAW3C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,aAAa,MAAM,EAAE,UAAU,GAAG,KAAG,MAYhF,CAAC;AAGF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,eAAe,MAAM,KAAG,iBAiEjE,CAAC"}
@@ -0,0 +1,130 @@
1
+ // noinspection UnnecessaryLocalVariableJS
2
+ import crypto from 'crypto';
3
+ import { appConfig } from '../bootstrap/init-config.js';
4
+ import { logger as lgr } from '../logger.js';
5
+ import { isObject, trim } from '../utils/utils.js';
6
+ import chalk from 'chalk';
7
+ const logger = lgr.getSubLogger({ name: chalk.cyan('token-auth') });
8
+ const { permanentServerTokens: pt, tokenEncryptKey } = appConfig.webServer.auth;
9
+ const permanentServerTokensSet = new Set(Array.isArray(pt) ? pt : [pt]);
10
+ const ALGORITHM = 'aes-256-ctr';
11
+ const KEY = crypto
12
+ .createHash('sha256')
13
+ .update(String(tokenEncryptKey))
14
+ .digest('base64')
15
+ .substring(0, 32);
16
+ export const tokenRE = /^(\d{13,})\.([\da-fA-F]{32,})$/;
17
+ /**
18
+ * Encrypts the transmitted text with a symmetric key taken from the config
19
+ */
20
+ export const encrypt = (text) => {
21
+ const buffer = Buffer.from(text);
22
+ // Create an initialization vector
23
+ const iv = crypto.randomBytes(16);
24
+ // Create a new cipher using the algorithm, key, and iv
25
+ const cipher = crypto.createCipheriv(ALGORITHM, KEY, iv);
26
+ // Create the new (encrypted) buffer
27
+ const encryptedBuf = Buffer.concat([iv, cipher.update(buffer), cipher.final()]);
28
+ return encryptedBuf.toString('hex');
29
+ };
30
+ /**
31
+ * Decrypts the transmitted text with a symmetric key taken from the config
32
+ */
33
+ export const decrypt = (encryptedStr) => {
34
+ const encryptedByf = Buffer.from(encryptedStr, 'hex');
35
+ // Get the iv: the first 16 bytes
36
+ const iv2 = encryptedByf.subarray(0, 16);
37
+ // Get the rest
38
+ const restBuf = encryptedByf.subarray(16);
39
+ // Create decipher
40
+ const decipher = crypto.createDecipheriv(ALGORITHM, KEY, iv2);
41
+ // Actually decrypt it
42
+ const decryptedBuf = Buffer.concat([decipher.update(restBuf), decipher.final()]);
43
+ return decryptedBuf.toString();
44
+ };
45
+ /**
46
+ * Creates a token by encrypting the username and expiration time.
47
+ * To determine the expiration time in the JB form script, at the beginning of the token
48
+ * deprecation timestamp is added
49
+ */
50
+ export const generateToken = (user, liveTimeSec, payload) => {
51
+ user = trim(user).toLowerCase();
52
+ if (!user) {
53
+ throw new Error('generateToken: Username is empty');
54
+ }
55
+ const expire = Date.now() + (liveTimeSec * 1000);
56
+ payload = isObject(payload) ? payload : {};
57
+ payload.user = user;
58
+ payload.expire = expire;
59
+ // Add the required serviceName parameter from appConfig
60
+ payload.serviceName = appConfig.name;
61
+ return `${expire}.${encrypt(JSON.stringify(payload))}`;
62
+ };
63
+ /**
64
+ * Checks the validity of the token:
65
+ * - Token to be decrypted
66
+ * - the obsolescence time must not be expired
67
+ * - If a user is transferred, it must match
68
+ */
69
+ export const checkToken = (token, expectedUser) => {
70
+ token = (token || '').trim();
71
+ if (!token) {
72
+ return {
73
+ errorReason: 'Token not passed',
74
+ };
75
+ }
76
+ if (permanentServerTokensSet.has(token)) {
77
+ return {
78
+ inTokenType: 'permanent',
79
+ };
80
+ }
81
+ const [, expirePartStr, encryptedPayload] = tokenRE.exec(token) || [];
82
+ if (!expirePartStr || !encryptedPayload) {
83
+ return {
84
+ inTokenType: 'permanent',
85
+ errorReason: 'The token is not a JWT and is not on the list of registered server tokens',
86
+ };
87
+ }
88
+ let payloadStr = '';
89
+ try {
90
+ payloadStr = decrypt(encryptedPayload);
91
+ }
92
+ catch (err) {
93
+ logger.error(err);
94
+ return {
95
+ errorReason: `Error decrypting JWT token :: ${err.message}`,
96
+ };
97
+ }
98
+ let payload;
99
+ try {
100
+ payload = JSON.parse(payloadStr);
101
+ }
102
+ catch (err) {
103
+ logger.error(err);
104
+ return {
105
+ inTokenType: 'JWT',
106
+ errorReason: `Error deserializing payload of JWT token :: ${err.message}`,
107
+ };
108
+ }
109
+ expectedUser = trim(expectedUser).toLowerCase();
110
+ if (expectedUser && payload.user !== expectedUser) {
111
+ return {
112
+ isTokenDecrypted: true,
113
+ inTokenType: 'JWT',
114
+ errorReason: `JWT Token: user not match :: Expected '${expectedUser}' / obtained from the token: '${payload.user}'`,
115
+ };
116
+ }
117
+ let expire = Number(expirePartStr) || 0;
118
+ const expiredOn = Date.now() - expire;
119
+ if (expiredOn > 0) {
120
+ // Token deprecated
121
+ return {
122
+ isTokenDecrypted: true,
123
+ inTokenType: 'JWT',
124
+ errorReason: `JWT Token expired :: on ${expiredOn} mc`,
125
+ };
126
+ }
127
+ // OK!
128
+ return { inTokenType: 'JWT', payload };
129
+ };
130
+ //# sourceMappingURL=token-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-core.js","sourceRoot":"","sources":["../../../src/core/token/token-core.ts"],"names":[],"mappings":"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"}