fa-mcp-sdk 0.2.146 → 0.2.174
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 +1 -1
- package/bin/fa-mcp.js +66 -54
- package/cli-template/.env.example +2 -2
- package/cli-template/README.md +2 -2
- package/cli-template/fa-mcp-sdk-spec.md +122 -41
- package/cli-template/package.json +3 -3
- package/cli-template/r/TEST HTTP.xml +9 -0
- package/cli-template/{run/TEST SSE.run.xml → r/TEST SSE.xml } +2 -2
- package/cli-template/{run/TEST STDIO.run.xml → r/TEST STDIO.xml } +2 -2
- package/cli-template/r/generate-token.xml +14 -0
- package/cli-template/{run/kill-server.run.xml → r/kill-server.xml} +2 -2
- package/cli-template/{run/kill-token-gen-server.xml → r/remove-nul.xml} +4 -5
- package/{cli-template/config → config}/_local.yaml +28 -14
- package/{cli-template/config → config}/custom-environment-variables.yaml +3 -0
- package/{cli-template/config → config}/default.yaml +50 -10
- package/{cli-template/config → config}/development.yaml +4 -4
- package/config/local.yaml +81 -0
- package/{cli-template/config → config}/production.yaml +4 -4
- package/dist/core/_types_/active-directory-config.d.ts +3 -0
- package/dist/core/_types_/active-directory-config.d.ts.map +1 -1
- package/dist/core/_types_/config.d.ts +5 -1
- package/dist/core/_types_/config.d.ts.map +1 -1
- package/dist/core/_types_/types.d.ts +5 -1
- package/dist/core/_types_/types.d.ts.map +1 -1
- package/dist/core/ad/group-checker.d.ts +13 -0
- package/dist/core/ad/group-checker.d.ts.map +1 -0
- package/dist/core/ad/group-checker.js +86 -0
- package/dist/core/ad/group-checker.js.map +1 -0
- package/dist/core/auth/admin-auth.d.ts +16 -0
- package/dist/core/auth/admin-auth.d.ts.map +1 -0
- package/dist/core/auth/admin-auth.js +159 -0
- package/dist/core/auth/admin-auth.js.map +1 -0
- package/dist/core/auth/basic.d.ts +6 -0
- package/dist/core/auth/basic.d.ts.map +1 -0
- package/dist/core/auth/basic.js +26 -0
- package/dist/core/auth/basic.js.map +1 -0
- package/dist/core/auth/{jwt-validation.d.ts → jwt.d.ts} +4 -3
- package/dist/core/auth/jwt.d.ts.map +1 -0
- package/dist/core/auth/{jwt-validation.js → jwt.js} +9 -19
- package/dist/core/auth/jwt.js.map +1 -0
- package/dist/core/auth/middleware.d.ts.map +1 -1
- package/dist/core/auth/middleware.js +3 -3
- package/dist/core/auth/middleware.js.map +1 -1
- package/dist/core/auth/multi-auth.d.ts +14 -6
- package/dist/core/auth/multi-auth.d.ts.map +1 -1
- package/dist/core/auth/multi-auth.js +151 -141
- package/dist/core/auth/multi-auth.js.map +1 -1
- package/dist/core/auth/permanent.d.ts +6 -0
- package/dist/core/auth/permanent.d.ts.map +1 -0
- package/dist/core/auth/permanent.js +15 -0
- package/dist/core/auth/permanent.js.map +1 -0
- package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.d.ts +1 -1
- package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.d.ts.map +1 -1
- package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.js +8 -10
- package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.js.map +1 -1
- package/dist/core/auth/token-generator/ntlm/ntlm-integration.d.ts.map +1 -1
- package/dist/core/auth/token-generator/ntlm/ntlm-integration.js +9 -2
- package/dist/core/auth/token-generator/ntlm/ntlm-integration.js.map +1 -1
- package/dist/core/auth/token-generator/server.d.ts.map +1 -1
- package/dist/core/auth/token-generator/server.js +59 -25
- package/dist/core/auth/token-generator/server.js.map +1 -1
- package/dist/core/auth/types.d.ts +4 -3
- package/dist/core/auth/types.d.ts.map +1 -1
- package/dist/core/bootstrap/startup-info.d.ts.map +1 -1
- package/dist/core/bootstrap/startup-info.js +19 -0
- package/dist/core/bootstrap/startup-info.js.map +1 -1
- package/dist/core/consul/access-points-updater.js +1 -1
- package/dist/core/consul/access-points-updater.js.map +1 -1
- package/dist/core/consul/get-consul-api.d.ts +1 -1
- package/dist/core/consul/get-consul-api.d.ts.map +1 -1
- package/dist/core/consul/get-consul-api.js +1 -1
- package/dist/core/consul/get-consul-api.js.map +1 -1
- package/dist/core/consul/register.d.ts +1 -1
- package/dist/core/consul/register.d.ts.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/init-mcp-server.d.ts.map +1 -1
- package/dist/core/init-mcp-server.js +1 -1
- package/dist/core/init-mcp-server.js.map +1 -1
- package/dist/core/utils/testing/McpSseClient.js.map +1 -1
- package/dist/core/web/admin-router.d.ts +10 -0
- package/dist/core/web/admin-router.d.ts.map +1 -0
- package/dist/core/web/admin-router.js +227 -0
- package/dist/core/web/admin-router.js.map +1 -0
- package/dist/core/web/favicon-svg.d.ts +1 -1
- package/dist/core/web/favicon-svg.d.ts.map +1 -1
- package/dist/core/web/favicon-svg.js +21 -3
- package/dist/core/web/favicon-svg.js.map +1 -1
- package/dist/core/web/home-api.d.ts +7 -0
- package/dist/core/web/home-api.d.ts.map +1 -0
- package/dist/core/web/home-api.js +93 -0
- package/dist/core/web/home-api.js.map +1 -0
- package/dist/core/web/server-http.d.ts +1 -0
- package/dist/core/web/server-http.d.ts.map +1 -1
- package/dist/core/web/server-http.js +60 -25
- package/dist/core/web/server-http.js.map +1 -1
- package/dist/core/web/static/home/index.html +206 -0
- package/dist/core/web/static/home/script.js +636 -0
- package/dist/core/web/{about-page/css.js → static/styles.css} +435 -105
- package/dist/core/web/static/token-gen/index.html +82 -0
- package/dist/core/web/static/token-gen/jwt-icon.svg +3 -0
- package/dist/core/web/static/token-gen/logout.svg +4 -0
- package/dist/core/web/static/token-gen/script.js +365 -0
- package/dist/core/web/static/token-gen/user.svg +4 -0
- package/dist/core/web/svg-icons.d.ts +7 -0
- package/dist/core/web/svg-icons.d.ts.map +1 -0
- package/dist/core/web/svg-icons.js +78 -0
- package/dist/core/web/svg-icons.js.map +1 -0
- package/package.json +7 -3
- package/scripts/copy-static.js +31 -0
- package/src/template/_examples/multi-auth-examples.ts +14 -47
- package/src/template/_types_/custom-config.ts +83 -0
- package/src/template/asset/logo.svg +4 -0
- package/src/template/start.ts +3 -3
- package/src/template/tools/handle-tool-call.ts +2 -1
- package/src/tests/mcp/test-http.js +10 -2
- package/src/tests/mcp/test-sse.js +10 -2
- package/src/tests/mcp/test-stdio.js +1 -2
- package/cli-template/run/TEST HTTP.run.xml +0 -5
- package/cli-template/run/TEST search.run.xml +0 -11
- package/cli-template/run/remove-nul.js.run.xml +0 -5
- package/dist/core/auth/jwt-validation.d.ts.map +0 -1
- package/dist/core/auth/jwt-validation.js.map +0 -1
- package/dist/core/auth/token-generator/html.d.ts +0 -9
- package/dist/core/auth/token-generator/html.d.ts.map +0 -1
- package/dist/core/auth/token-generator/html.js +0 -862
- package/dist/core/auth/token-generator/html.js.map +0 -1
- package/dist/core/web/about-page/css.d.ts +0 -2
- package/dist/core/web/about-page/css.d.ts.map +0 -1
- package/dist/core/web/about-page/css.js.map +0 -1
- package/dist/core/web/about-page/render.d.ts +0 -2
- package/dist/core/web/about-page/render.d.ts.map +0 -1
- package/dist/core/web/about-page/render.js +0 -773
- package/dist/core/web/about-page/render.js.map +0 -1
- /package/cli-template/{run/== START ==.run.xml → r/== START ==.xml} +0 -0
- /package/cli-template/{run/cb.run.xml → r/cb.xml} +0 -0
- /package/cli-template/{run/ci.run.xml → r/ci.xml} +0 -0
- /package/cli-template/{run/lint.run.xml → r/lint.xml} +0 -0
- /package/cli-template/{run/lint_fix.run.xml → r/lint_fix.xml} +0 -0
- /package/cli-template/{run/reinstall.run.xml → r/reinstall.xml} +0 -0
- /package/{cli-template/config → config}/test.yaml +0 -0
- /package/{src/template/asset/favicon.svg → dist/core/web/static/logo.svg} +0 -0
- /package/{cli-template/scripts → scripts}/kill-port.js +0 -0
- /package/{cli-template/scripts → scripts}/npm/patch_node_modules.js +0 -0
- /package/{cli-template/scripts → scripts}/npm/run.js +0 -0
- /package/{cli-template/scripts → scripts}/npm/yarn-ci.ps1 +0 -0
- /package/{cli-template/scripts → scripts}/npm/yarn-ci.sh +0 -0
- /package/{cli-template/scripts → scripts}/npm/yarn-reinstall.ps1 +0 -0
- /package/{cli-template/scripts → scripts}/npm/yarn-reinstall.sh +0 -0
- /package/{cli-template/scripts → scripts}/pre-commit +0 -0
- /package/{cli-template/scripts → scripts}/remove-nul.js +0 -0
|
@@ -1,862 +0,0 @@
|
|
|
1
|
-
import { encodeSvgForDataUri } from '../../utils/utils.js';
|
|
2
|
-
const jwtSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#0052cc" d="M10.2 0v6.5L12 8.9l1.8-2.4V0Zm3.6 6.5v3l3-1 3.7-5.1-2.9-2.2zm3 2-1.9 2.6 3 1 6.1-2-1.1-3.5Zm1 3.5L15 13l1.8 2.5 6.2 2 1-3.5Zm-1 3.5-3-1v3l3.8 5.3 3-2.1zm-3 2L12 15.2l-1.8 2.5V24h3.6zm-3.6 0v-3l-3 1-3.7 5.2 2.9 2.1zm-3-2 2-2.5-3-1L0 14l1.1 3.5Zm-1-3.5L9 11 7.3 8.7 1 6.6 0 10Zm1-3.4 3 1V6.4L6.4 1.2l-3 2.2Z"/></svg>';
|
|
3
|
-
const iconEncoded = encodeSvgForDataUri(jwtSvg);
|
|
4
|
-
export const getHTMLPage = (authStatus) => `<!DOCTYPE html>
|
|
5
|
-
<html lang='ru'>
|
|
6
|
-
<head>
|
|
7
|
-
<meta charset='UTF-8'>
|
|
8
|
-
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
|
|
9
|
-
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,${iconEncoded}">
|
|
10
|
-
<title>Token Generator & Validator</title>
|
|
11
|
-
|
|
12
|
-
<style>
|
|
13
|
-
* {
|
|
14
|
-
box-sizing: border-box;
|
|
15
|
-
margin: 0;
|
|
16
|
-
padding: 0;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
html, body {
|
|
20
|
-
height: 100%;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
body {
|
|
24
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
25
|
-
font-size: 14px;
|
|
26
|
-
line-height: 1.5;
|
|
27
|
-
color: #253858;
|
|
28
|
-
background: white;
|
|
29
|
-
margin: 0;
|
|
30
|
-
padding: 24px;
|
|
31
|
-
-webkit-font-smoothing: antialiased;
|
|
32
|
-
-moz-osx-font-smoothing: grayscale;
|
|
33
|
-
min-height: 100vh;
|
|
34
|
-
display: flex;
|
|
35
|
-
align-items: flex-start;
|
|
36
|
-
justify-content: center;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/* Simple Layout */
|
|
40
|
-
.simple-container {
|
|
41
|
-
width: 100%;
|
|
42
|
-
max-width: 670px;
|
|
43
|
-
background: white;
|
|
44
|
-
border: 1px solid #c1c7d0;
|
|
45
|
-
border-radius: 6px;
|
|
46
|
-
box-shadow: 0 1px 3px rgba(9, 30, 66, 0.25), 0 0 1px rgba(9, 30, 66, 0.31);
|
|
47
|
-
margin-top: 40px;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/* Simple Header */
|
|
51
|
-
.simple-header {
|
|
52
|
-
padding: 16px 24px 12px;
|
|
53
|
-
border-bottom: 1px solid #c1c7d0;
|
|
54
|
-
background: #fafbfc;
|
|
55
|
-
border-radius: 6px 6px 0 0;
|
|
56
|
-
display: flex;
|
|
57
|
-
align-items: center;
|
|
58
|
-
gap: 16px;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.simple-header h1 {
|
|
62
|
-
font-size: 24px;
|
|
63
|
-
font-weight: 600;
|
|
64
|
-
margin: 0;
|
|
65
|
-
color: #0052cc;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/* Simple Main Content */
|
|
69
|
-
.simple-main {
|
|
70
|
-
padding: 24px 24px;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.tab-container {
|
|
74
|
-
margin-bottom: 0;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.tabs {
|
|
78
|
-
display: flex;
|
|
79
|
-
border-bottom: 1px solid #c1c7d0;
|
|
80
|
-
margin-bottom: 24px;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.tab {
|
|
84
|
-
background: none;
|
|
85
|
-
border: none;
|
|
86
|
-
padding: 12px 16px;
|
|
87
|
-
cursor: pointer;
|
|
88
|
-
font-size: 14px;
|
|
89
|
-
font-weight: 500;
|
|
90
|
-
color: #505f79;
|
|
91
|
-
border-bottom: 2px solid transparent;
|
|
92
|
-
transition: all 0.2s ease;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.tab.active {
|
|
96
|
-
color: #0052cc;
|
|
97
|
-
border-bottom-color: #0052cc;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.tab:hover {
|
|
101
|
-
color: #253858;
|
|
102
|
-
background: #fafbfc;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.tab-content {
|
|
106
|
-
display: none;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.tab-content.active {
|
|
110
|
-
display: block;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.form-group {
|
|
114
|
-
margin-bottom: 12px;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.form-row {
|
|
118
|
-
display: flex;
|
|
119
|
-
gap: 12px;
|
|
120
|
-
align-items: center;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
label {
|
|
124
|
-
display: block;
|
|
125
|
-
margin-bottom: 4px;
|
|
126
|
-
font-weight: 500;
|
|
127
|
-
color: #42526e;
|
|
128
|
-
font-size: 14px;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
input, select, textarea {
|
|
132
|
-
width: 100%;
|
|
133
|
-
padding: 4px 6px;
|
|
134
|
-
border: 1px solid #c1c7d0;
|
|
135
|
-
border-radius: 3px;
|
|
136
|
-
font-size: 14px;
|
|
137
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
138
|
-
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
|
139
|
-
background: white;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
select {
|
|
143
|
-
padding: 3px 6px;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
input:focus, select:focus, textarea:focus {
|
|
147
|
-
outline: none;
|
|
148
|
-
border-color: #0065ff;
|
|
149
|
-
box-shadow: 0 0 0 2px rgba(0, 101, 255, 0.1);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
input::placeholder, textarea::placeholder {
|
|
153
|
-
color: #505f79;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.time-input {
|
|
157
|
-
flex: 1;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.time-unit {
|
|
161
|
-
flex: 0 0 120px;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.key-value-pair {
|
|
165
|
-
display: flex;
|
|
166
|
-
gap: 8px;
|
|
167
|
-
margin-bottom: 12px;
|
|
168
|
-
align-items: center;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
.key-value-pair input {
|
|
172
|
-
margin-bottom: 0;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
.key-value-pair input[name="keys"] {
|
|
176
|
-
width: 180px;
|
|
177
|
-
flex-shrink: 0;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.key-value-pair input[name="values"] {
|
|
181
|
-
flex: 1;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
.remove-btn {
|
|
185
|
-
background: white;
|
|
186
|
-
color: #bf2600;
|
|
187
|
-
border: 0px;
|
|
188
|
-
width: 28px;
|
|
189
|
-
height: 28px;
|
|
190
|
-
cursor: pointer;
|
|
191
|
-
font-size: 22px;
|
|
192
|
-
display: flex;
|
|
193
|
-
align-items: center;
|
|
194
|
-
justify-content: center;
|
|
195
|
-
flex-shrink: 0;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.remove-btn:hover {
|
|
199
|
-
background: #bf2600;
|
|
200
|
-
color: white;
|
|
201
|
-
border-color: #bf2600;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.add-btn {
|
|
205
|
-
background: #d7ffd4;
|
|
206
|
-
color: #089300;
|
|
207
|
-
border: none;
|
|
208
|
-
border-radius: 14px;
|
|
209
|
-
width: 28px;
|
|
210
|
-
height: 28px;
|
|
211
|
-
cursor: pointer;
|
|
212
|
-
font-size: 24px;
|
|
213
|
-
font-weight: 500;
|
|
214
|
-
align-items: center;
|
|
215
|
-
transition: background 0.2s ease;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
.add-btn:hover {
|
|
219
|
-
background: #c9ffc4;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
.btn {
|
|
223
|
-
background: #0052cc;
|
|
224
|
-
color: white;
|
|
225
|
-
border: none;
|
|
226
|
-
padding: 12px 24px;
|
|
227
|
-
border-radius: 3px;
|
|
228
|
-
font-size: 14px;
|
|
229
|
-
font-weight: 500;
|
|
230
|
-
cursor: pointer;
|
|
231
|
-
transition: all 0.2s ease;
|
|
232
|
-
width: 100%;
|
|
233
|
-
margin-bottom: 16px;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
.btn:hover {
|
|
237
|
-
background: #0065ff;
|
|
238
|
-
box-shadow: 0 1px 1px rgba(9, 30, 66, 0.25), 0 0 1px rgba(9, 30, 66, 0.31);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
.btn:active {
|
|
242
|
-
transform: translateY(1px);
|
|
243
|
-
box-shadow: none;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
.result {
|
|
248
|
-
margin-top: 24px;
|
|
249
|
-
padding: 24px;
|
|
250
|
-
border-radius: 3px;
|
|
251
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
.result.success {
|
|
255
|
-
background: rgba(0, 102, 68, 0.1);
|
|
256
|
-
color: #006644;
|
|
257
|
-
border: 1px solid rgba(0, 102, 68, 0.2);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.result.error {
|
|
261
|
-
background: rgba(191, 38, 0, 0.1);
|
|
262
|
-
color: #bf2600;
|
|
263
|
-
border: 1px solid rgba(255, 86, 48, 0.2);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
.token-output {
|
|
267
|
-
background: #ebecf0;
|
|
268
|
-
border: 1px solid #c1c7d0;
|
|
269
|
-
border-radius: 3px;
|
|
270
|
-
padding: 16px;
|
|
271
|
-
font-family: ui-monospace, 'SF Mono', 'Consolas', 'Roboto Mono', 'Ubuntu Mono', monospace;
|
|
272
|
-
font-size: 12px;
|
|
273
|
-
line-height: 1.4;
|
|
274
|
-
word-break: break-all;
|
|
275
|
-
min-height: 100px;
|
|
276
|
-
resize: vertical;
|
|
277
|
-
color: #172b4d;
|
|
278
|
-
position: relative;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.copy-button, .validate-token-button {
|
|
282
|
-
position: absolute;
|
|
283
|
-
bottom: 5px;
|
|
284
|
-
right: 35px;
|
|
285
|
-
background: #ffffff73;
|
|
286
|
-
border-radius: 4px;
|
|
287
|
-
width: 28px;
|
|
288
|
-
height: 28px;
|
|
289
|
-
cursor: pointer;
|
|
290
|
-
font-size: 12px;
|
|
291
|
-
display: flex;
|
|
292
|
-
align-items: center;
|
|
293
|
-
justify-content: center;
|
|
294
|
-
border: none;
|
|
295
|
-
transition: all 0.2s ease;
|
|
296
|
-
z-index: 10;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
.validate-token-button {
|
|
300
|
-
right: 5px;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
.copy-button:hover, .validate-token-button:hover {
|
|
304
|
-
background: #ffffff;
|
|
305
|
-
transform: scale(1.05);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
.copy-notification {
|
|
309
|
-
position: absolute;
|
|
310
|
-
top: 8px;
|
|
311
|
-
right: 42px;
|
|
312
|
-
background: #006644;
|
|
313
|
-
color: white;
|
|
314
|
-
padding: 4px 8px;
|
|
315
|
-
border-radius: 4px;
|
|
316
|
-
font-size: 12px;
|
|
317
|
-
font-weight: 500;
|
|
318
|
-
opacity: 0;
|
|
319
|
-
transform: translateY(-10px);
|
|
320
|
-
transition: all 0.3s ease;
|
|
321
|
-
z-index: 11;
|
|
322
|
-
white-space: nowrap;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
.copy-notification.show {
|
|
326
|
-
opacity: 1;
|
|
327
|
-
transform: translateY(0);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
.token-info {
|
|
331
|
-
background: rgba(0, 102, 68, 0.05);
|
|
332
|
-
border: 1px solid rgba(0, 102, 68, 0.1);
|
|
333
|
-
border-radius: 3px;
|
|
334
|
-
padding: 16px;
|
|
335
|
-
margin-top: 12px;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
.token-info h4 {
|
|
339
|
-
margin-bottom: 8px;
|
|
340
|
-
color: #006644;
|
|
341
|
-
font-weight: 600;
|
|
342
|
-
font-size: 14px;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
.token-info p {
|
|
346
|
-
margin: 4px 0;
|
|
347
|
-
font-family: ui-monospace, 'SF Mono', 'Consolas', 'Roboto Mono', 'Ubuntu Mono', monospace;
|
|
348
|
-
font-size: 14px;
|
|
349
|
-
color: #172b4d;
|
|
350
|
-
}
|
|
351
|
-
.service-icon {
|
|
352
|
-
width: 26px;
|
|
353
|
-
height: 26px;
|
|
354
|
-
display: flex;
|
|
355
|
-
align-items: center;
|
|
356
|
-
justify-content: center;
|
|
357
|
-
}
|
|
358
|
-
.service-icon svg {
|
|
359
|
-
width: 100%;
|
|
360
|
-
height: 100%;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/* Authentication status */
|
|
364
|
-
.auth-status {
|
|
365
|
-
padding: 12px 16px;
|
|
366
|
-
margin-bottom: 16px;
|
|
367
|
-
border-radius: 4px;
|
|
368
|
-
display: flex;
|
|
369
|
-
justify-content: space-between;
|
|
370
|
-
align-items: center;
|
|
371
|
-
font-size: 14px;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
.auth-status.auth-enabled {
|
|
375
|
-
background: rgba(0, 102, 68, 0.1);
|
|
376
|
-
border: 1px solid rgba(0, 102, 68, 0.2);
|
|
377
|
-
color: #006644;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
.auth-status.auth-disabled {
|
|
381
|
-
background: rgba(245, 158, 11, 0.1);
|
|
382
|
-
border: 1px solid rgba(245, 158, 11, 0.2);
|
|
383
|
-
color: #d97706;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
.auth-info {
|
|
387
|
-
display: flex;
|
|
388
|
-
align-items: center;
|
|
389
|
-
gap: 8px;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
.auth-indicator {
|
|
393
|
-
display: inline-block;
|
|
394
|
-
width: 8px;
|
|
395
|
-
height: 8px;
|
|
396
|
-
border-radius: 50%;
|
|
397
|
-
margin-right: 4px;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
.auth-indicator.enabled {
|
|
401
|
-
background: #006644;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
.auth-indicator.disabled {
|
|
405
|
-
background: #d97706;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.logout-btn {
|
|
409
|
-
background: #dc2626;
|
|
410
|
-
color: white;
|
|
411
|
-
border: none;
|
|
412
|
-
padding: 6px 12px;
|
|
413
|
-
border-radius: 3px;
|
|
414
|
-
font-size: 12px;
|
|
415
|
-
cursor: pointer;
|
|
416
|
-
transition: background 0.2s ease;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
.logout-btn:hover {
|
|
420
|
-
background: #b91c1c;
|
|
421
|
-
}
|
|
422
|
-
/* Responsive Design */
|
|
423
|
-
@media (max-width: 640px) {
|
|
424
|
-
body {
|
|
425
|
-
padding: 16px;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
.simple-container {
|
|
429
|
-
margin-top: 24px;
|
|
430
|
-
max-width: 100%;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
.simple-header {
|
|
434
|
-
padding: 16px 20px 12px;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
.simple-header h1 {
|
|
438
|
-
font-size: 20px;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
.simple-main {
|
|
442
|
-
padding: 20px 20px;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
.form-row {
|
|
446
|
-
flex-direction: column;
|
|
447
|
-
gap: 8px;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
.key-value-pair {
|
|
451
|
-
flex-direction: column;
|
|
452
|
-
align-items: stretch;
|
|
453
|
-
gap: 8px;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
.key-value-pair input[name="keys"] {
|
|
457
|
-
width: 100%;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
.remove-btn {
|
|
461
|
-
width: 100%;
|
|
462
|
-
margin-top: 8px;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
</style>
|
|
466
|
-
</head>
|
|
467
|
-
<body>
|
|
468
|
-
<div class="simple-container">
|
|
469
|
-
<!-- Header -->
|
|
470
|
-
<header class="simple-header">
|
|
471
|
-
<div class="service-icon">${jwtSvg}</div>
|
|
472
|
-
<h1>Token Generator & Validator</h1>
|
|
473
|
-
</header>
|
|
474
|
-
|
|
475
|
-
<!-- Authentication Status -->
|
|
476
|
-
<main class="simple-main">
|
|
477
|
-
${authStatus ? `
|
|
478
|
-
<div class="auth-status ${authStatus.ntlmEnabled ? 'auth-enabled' : 'auth-disabled'}">
|
|
479
|
-
<div class="auth-info">
|
|
480
|
-
<span>
|
|
481
|
-
<span class="auth-indicator ${authStatus.ntlmEnabled ? 'enabled' : 'disabled'}"></span>
|
|
482
|
-
NTLM Authentication: ${authStatus.ntlmEnabled ? 'Enabled' : 'Disabled'}
|
|
483
|
-
${authStatus.ntlmEnabled && authStatus.isAuthenticated ? `- Logged in as ${authStatus.domain}\\${authStatus.username}` : ''}
|
|
484
|
-
</span>
|
|
485
|
-
</div>
|
|
486
|
-
${authStatus.ntlmEnabled && authStatus.isAuthenticated ? `
|
|
487
|
-
<button class="logout-btn" onclick="logout()">Log out</button>
|
|
488
|
-
` : ''}
|
|
489
|
-
</div>
|
|
490
|
-
` : ''}
|
|
491
|
-
|
|
492
|
-
<div class="tab-container">
|
|
493
|
-
<div class="tabs">
|
|
494
|
-
<button class="tab active" onclick="switchTab('generate')">Token generation</button>
|
|
495
|
-
<button class="tab" onclick="switchTab('validate')">Token validation</button>
|
|
496
|
-
</div>
|
|
497
|
-
|
|
498
|
-
<!-- Token generation -->
|
|
499
|
-
<div id="generate" class="tab-content active">
|
|
500
|
-
<form id="generateForm">
|
|
501
|
-
<div class="form-group">
|
|
502
|
-
<div class="form-row" style="gap: 20px;">
|
|
503
|
-
<div style="flex: 1;">
|
|
504
|
-
<label for="tokenUser">Who is the token issued to:</label>
|
|
505
|
-
<input type="text" id="tokenUser" name="user" required>
|
|
506
|
-
</div>
|
|
507
|
-
<div style="flex: 1;">
|
|
508
|
-
<label>For how long:</label>
|
|
509
|
-
<div class="form-row">
|
|
510
|
-
<input type="number" id="timeValue" name="timeValue" class="time-input" min="1" required>
|
|
511
|
-
<select id="timeUnit" name="timeUnit" class="time-unit">
|
|
512
|
-
<option value="minutes">minutes</option>
|
|
513
|
-
<option value="hours">hours</option>
|
|
514
|
-
<option value="days" selected>days</option>
|
|
515
|
-
<option value="months">months</option>
|
|
516
|
-
<option value="years">years</option>
|
|
517
|
-
</select>
|
|
518
|
-
</div>
|
|
519
|
-
</div>
|
|
520
|
-
</div>
|
|
521
|
-
</div>
|
|
522
|
-
<div class="form-group">
|
|
523
|
-
<label>Additional data (key-value):</label>
|
|
524
|
-
<div id="keyValuePairs"></div>
|
|
525
|
-
<button type="button" class="add-btn" onclick="addKeyValuePair()">+</button>
|
|
526
|
-
</div>
|
|
527
|
-
<button type="submit" class="btn">Generate a token</button>
|
|
528
|
-
</form>
|
|
529
|
-
<div id="generateResult"></div>
|
|
530
|
-
</div>
|
|
531
|
-
|
|
532
|
-
<!-- Token validation -->
|
|
533
|
-
<div id="validate" class="tab-content">
|
|
534
|
-
<form id="validateForm">
|
|
535
|
-
<div class="form-group">
|
|
536
|
-
<label for="tokenInput">Enter the token for verification:</label>
|
|
537
|
-
<textarea id="tokenInput" name="token" rows="4" required></textarea>
|
|
538
|
-
</div>
|
|
539
|
-
<button type="submit" class="btn">Check Token</button>
|
|
540
|
-
</form>
|
|
541
|
-
<div id="validateResult"></div>
|
|
542
|
-
</div>
|
|
543
|
-
</div>
|
|
544
|
-
</main>
|
|
545
|
-
</div>
|
|
546
|
-
|
|
547
|
-
<script>
|
|
548
|
-
let keyValuePairCount = 0;
|
|
549
|
-
|
|
550
|
-
function switchTab (tabName) {
|
|
551
|
-
document.querySelectorAll('.tab-content').forEach(content => {
|
|
552
|
-
content.classList.remove('active');
|
|
553
|
-
});
|
|
554
|
-
document.querySelectorAll('.tab').forEach(tab => {
|
|
555
|
-
tab.classList.remove('active');
|
|
556
|
-
});
|
|
557
|
-
document.getElementById(tabName).classList.add('active');
|
|
558
|
-
|
|
559
|
-
// Activate the corresponding tab button
|
|
560
|
-
const tabs = document.querySelectorAll('.tab');
|
|
561
|
-
tabs.forEach(tab => {
|
|
562
|
-
const onclick = tab.getAttribute('onclick');
|
|
563
|
-
if (onclick && onclick.includes('switchTab(\'' + tabName + '\')')) {
|
|
564
|
-
tab.classList.add('active');
|
|
565
|
-
}
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
function addKeyValuePair (key = '', value = '', readonly = false, placeholder = 'Value') {
|
|
570
|
-
if (keyValuePairCount >= 15) {
|
|
571
|
-
alert('Maximum of 15 key-value pairs');
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
const container = document.getElementById('keyValuePairs');
|
|
575
|
-
const pairDiv = document.createElement('div');
|
|
576
|
-
pairDiv.className = 'key-value-pair';
|
|
577
|
-
|
|
578
|
-
const keyInput = readonly ?
|
|
579
|
-
'<input type="text" placeholder="Key" name="keys" value="' + key + '" readonly style="background-color: #f8f9fa;">' :
|
|
580
|
-
'<input type="text" placeholder="Key" name="keys" value="' + key + '">';
|
|
581
|
-
|
|
582
|
-
const valueInput = '<input type="text" placeholder="' + placeholder + '" name="values" value="' + value + '">';
|
|
583
|
-
|
|
584
|
-
pairDiv.innerHTML = keyInput + valueInput +
|
|
585
|
-
'<button type="button" class="remove-btn" onclick="removeKeyValuePair(this)">×</button>';
|
|
586
|
-
container.appendChild(pairDiv);
|
|
587
|
-
keyValuePairCount++;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function removeKeyValuePair (button) {
|
|
591
|
-
button.parentElement.remove();
|
|
592
|
-
keyValuePairCount--;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
function addCopyButtonToTokenOutput(tokenOutput, token) {
|
|
596
|
-
if (!tokenOutput || tokenOutput.hasAttribute('data-copy-added')) {
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
tokenOutput.setAttribute('data-copy-added', 'true');
|
|
601
|
-
|
|
602
|
-
const copyButton = document.createElement('button');
|
|
603
|
-
copyButton.className = 'copy-button';
|
|
604
|
-
copyButton.innerHTML = '📋';
|
|
605
|
-
copyButton.title = 'Copy to clipboard';
|
|
606
|
-
copyButton.setAttribute('aria-label', 'Copy to clipboard');
|
|
607
|
-
|
|
608
|
-
const validateButton = document.createElement('button');
|
|
609
|
-
validateButton.className = 'validate-token-button';
|
|
610
|
-
validateButton.innerHTML = '✓';
|
|
611
|
-
validateButton.title = 'Validate token';
|
|
612
|
-
validateButton.setAttribute('aria-label', 'Validate token');
|
|
613
|
-
|
|
614
|
-
const notification = document.createElement('div');
|
|
615
|
-
notification.className = 'copy-notification';
|
|
616
|
-
notification.textContent = 'Copied';
|
|
617
|
-
|
|
618
|
-
tokenOutput.appendChild(copyButton);
|
|
619
|
-
tokenOutput.appendChild(validateButton);
|
|
620
|
-
tokenOutput.appendChild(notification);
|
|
621
|
-
|
|
622
|
-
copyButton.addEventListener('click', async function() {
|
|
623
|
-
try {
|
|
624
|
-
await navigator.clipboard.writeText(token);
|
|
625
|
-
|
|
626
|
-
// Show notification
|
|
627
|
-
notification.classList.add('show');
|
|
628
|
-
|
|
629
|
-
// Hide notification after 1 second
|
|
630
|
-
setTimeout(() => {
|
|
631
|
-
notification.classList.remove('show');
|
|
632
|
-
}, 1000);
|
|
633
|
-
|
|
634
|
-
} catch (err) {
|
|
635
|
-
// Fallback for browsers that don't support clipboard API
|
|
636
|
-
const textArea = document.createElement('textarea');
|
|
637
|
-
textArea.value = token;
|
|
638
|
-
textArea.style.position = 'fixed';
|
|
639
|
-
textArea.style.opacity = '0';
|
|
640
|
-
document.body.appendChild(textArea);
|
|
641
|
-
textArea.focus();
|
|
642
|
-
textArea.select();
|
|
643
|
-
|
|
644
|
-
try {
|
|
645
|
-
document.execCommand('copy');
|
|
646
|
-
|
|
647
|
-
// Show notification
|
|
648
|
-
notification.classList.add('show');
|
|
649
|
-
|
|
650
|
-
// Hide notification after 1 second
|
|
651
|
-
setTimeout(() => {
|
|
652
|
-
notification.classList.remove('show');
|
|
653
|
-
}, 1000);
|
|
654
|
-
} catch (fallbackErr) {
|
|
655
|
-
console.error('Failed to copy text:', fallbackErr);
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
document.body.removeChild(textArea);
|
|
659
|
-
}
|
|
660
|
-
});
|
|
661
|
-
|
|
662
|
-
validateButton.addEventListener('click', function() {
|
|
663
|
-
// Switch to validation tab
|
|
664
|
-
switchTab('validate');
|
|
665
|
-
|
|
666
|
-
// Set the token in the validation textarea
|
|
667
|
-
const tokenTextarea = document.getElementById('tokenInput');
|
|
668
|
-
if (tokenTextarea) {
|
|
669
|
-
tokenTextarea.value = token;
|
|
670
|
-
|
|
671
|
-
// Trigger validation form submit
|
|
672
|
-
const validateForm = document.getElementById('validateForm');
|
|
673
|
-
if (validateForm) {
|
|
674
|
-
validateForm.dispatchEvent(new Event('submit'));
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
function formatTime (ms) {
|
|
681
|
-
const seconds = Math.floor(ms / 1000);
|
|
682
|
-
const minutes = Math.floor(seconds / 60);
|
|
683
|
-
const hours = Math.floor(minutes / 60);
|
|
684
|
-
const days = Math.floor(hours / 24);
|
|
685
|
-
|
|
686
|
-
if (days > 0) return days + ' d. ' + (hours % 24) + ' h.';
|
|
687
|
-
if (hours > 0) return hours + ' h. ' + (minutes % 60) + ' min.';
|
|
688
|
-
if (minutes > 0) return minutes + ' min.';
|
|
689
|
-
return seconds + ' s.';
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
// Processing the Generation Form
|
|
693
|
-
document.getElementById('generateForm').addEventListener('submit', async (e) => {
|
|
694
|
-
e.preventDefault();
|
|
695
|
-
|
|
696
|
-
const formData = new FormData(e.target);
|
|
697
|
-
const keys = formData.getAll('keys').filter(k => k.trim());
|
|
698
|
-
const values = formData.getAll('values').filter(v => v.trim());
|
|
699
|
-
|
|
700
|
-
const payload = {};
|
|
701
|
-
for (let i = 0; i < keys.length; i++) {
|
|
702
|
-
if (keys[i] && values[i]) {
|
|
703
|
-
payload[keys[i]] = values[i];
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
const requestData = {
|
|
708
|
-
user: formData.get('user'),
|
|
709
|
-
timeValue: parseInt(formData.get('timeValue')),
|
|
710
|
-
timeUnit: formData.get('timeUnit'),
|
|
711
|
-
payload: payload,
|
|
712
|
-
};
|
|
713
|
-
|
|
714
|
-
try {
|
|
715
|
-
const response = await fetch('/api/generate-token', {
|
|
716
|
-
method: 'POST',
|
|
717
|
-
headers: { 'Content-Type': 'application/json' },
|
|
718
|
-
body: JSON.stringify(requestData),
|
|
719
|
-
});
|
|
720
|
-
|
|
721
|
-
const result = await response.json();
|
|
722
|
-
const resultDiv = document.getElementById('generateResult');
|
|
723
|
-
|
|
724
|
-
if (result.success) {
|
|
725
|
-
resultDiv.innerHTML =
|
|
726
|
-
'<div class="result success">' +
|
|
727
|
-
'<strong>The token has been successfully created!</strong><br>' +
|
|
728
|
-
'<div class="token-output">' + result.token + '</div>' +
|
|
729
|
-
'</div>';
|
|
730
|
-
|
|
731
|
-
// Add floating copy button to the token output
|
|
732
|
-
const tokenOutput = resultDiv.querySelector('.token-output');
|
|
733
|
-
if (tokenOutput) {
|
|
734
|
-
addCopyButtonToTokenOutput(tokenOutput, result.token);
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// Automatically populate the validation field with the generated token
|
|
738
|
-
const tokenTextarea = document.getElementById('tokenInput');
|
|
739
|
-
if (tokenTextarea) {
|
|
740
|
-
tokenTextarea.value = result.token;
|
|
741
|
-
}
|
|
742
|
-
} else {
|
|
743
|
-
resultDiv.innerHTML =
|
|
744
|
-
'<div class="result error">' +
|
|
745
|
-
'<strong>Error:</strong> ' + result.error +
|
|
746
|
-
'</div>';
|
|
747
|
-
}
|
|
748
|
-
} catch (error) {
|
|
749
|
-
document.getElementById('generateResult').innerHTML =
|
|
750
|
-
'<div class="result error">' +
|
|
751
|
-
'<strong>Error:</strong> ' + error.message +
|
|
752
|
-
'</div>';
|
|
753
|
-
}
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
// Processing the Verification Form
|
|
757
|
-
document.getElementById('validateForm').addEventListener('submit', async (e) => {
|
|
758
|
-
e.preventDefault();
|
|
759
|
-
|
|
760
|
-
const formData = new FormData(e.target);
|
|
761
|
-
const token = formData.get('token').trim();
|
|
762
|
-
|
|
763
|
-
try {
|
|
764
|
-
const response = await fetch('/api/validate-token', {
|
|
765
|
-
method: 'POST',
|
|
766
|
-
headers: { 'Content-Type': 'application/json' },
|
|
767
|
-
body: JSON.stringify({ token }),
|
|
768
|
-
});
|
|
769
|
-
|
|
770
|
-
const result = await response.json();
|
|
771
|
-
const resultDiv = document.getElementById('validateResult');
|
|
772
|
-
|
|
773
|
-
if (result.success) {
|
|
774
|
-
const remainingTime = result.payload.expire - Date.now();
|
|
775
|
-
const payloadKeys = Object.keys(result.payload).filter((k) => !/^(user|expire|iat|service)$/.test(k));
|
|
776
|
-
|
|
777
|
-
let payloadHtml = '';
|
|
778
|
-
if (payloadKeys.length > 0) {
|
|
779
|
-
payloadHtml = '<h4>Additional data:</h4>';
|
|
780
|
-
payloadKeys.forEach(key => {
|
|
781
|
-
payloadHtml += '<p><strong>' + key + ':</strong> ' + result.payload[key] + '</p>';
|
|
782
|
-
});
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
// Format issued at time
|
|
786
|
-
const issuedAtTime = result.payload.iat ? new Date(result.payload.iat).toLocaleString('ru-RU') : 'N/A';
|
|
787
|
-
|
|
788
|
-
resultDiv.innerHTML =
|
|
789
|
-
'<div class="result success">' +
|
|
790
|
-
'<strong>The token is valid!</strong>' +
|
|
791
|
-
'<div class="token-info">' +
|
|
792
|
-
'<h4>Token Information:</h4>' +
|
|
793
|
-
'<p><strong>User:</strong> ' + result.payload.user + '</p>' +
|
|
794
|
-
( result.payload.service ? '<p><strong>Service:</strong> ' + result.payload.service + '</p>' : '') +
|
|
795
|
-
'<p><strong>Issued at:</strong> ' + issuedAtTime + '</p>' +
|
|
796
|
-
'<p><strong>Time remaining:</strong> ' + formatTime(remainingTime) + '</p>' +
|
|
797
|
-
'<p><strong>Expires:</strong> ' + new Date(result.payload.expire).toLocaleString('ru-RU') + '</p>' +
|
|
798
|
-
payloadHtml +
|
|
799
|
-
'</div>' +
|
|
800
|
-
'</div>';
|
|
801
|
-
} else {
|
|
802
|
-
resultDiv.innerHTML =
|
|
803
|
-
'<div class="result error">' +
|
|
804
|
-
'<strong>Token invalid!</strong><br>' +
|
|
805
|
-
'Reason: ' + result.error +
|
|
806
|
-
'</div>';
|
|
807
|
-
}
|
|
808
|
-
} catch (error) {
|
|
809
|
-
document.getElementById('validateResult').innerHTML =
|
|
810
|
-
'<div class="result error">' +
|
|
811
|
-
'<strong>Error:</strong> ' + error.message +
|
|
812
|
-
'</div>';
|
|
813
|
-
}
|
|
814
|
-
});
|
|
815
|
-
|
|
816
|
-
// Function to initialize the form
|
|
817
|
-
async function initializeForm () {
|
|
818
|
-
try {
|
|
819
|
-
// Getting information about the service
|
|
820
|
-
const response = await fetch('/api/service-info');
|
|
821
|
-
const data = await response.json();
|
|
822
|
-
const serviceName = data.serviceName;
|
|
823
|
-
|
|
824
|
-
// Adding a pre-filled pair serviceName
|
|
825
|
-
addKeyValuePair('service', serviceName, true);
|
|
826
|
-
addKeyValuePair('issue', '', true, 'URL of request for the issuance of a token in JIRA');
|
|
827
|
-
|
|
828
|
-
} catch (error) {
|
|
829
|
-
console.error('Error loading service info:', error);
|
|
830
|
-
}
|
|
831
|
-
// Add one empty pair for the user
|
|
832
|
-
addKeyValuePair();
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
// Logout function
|
|
836
|
-
async function logout() {
|
|
837
|
-
try {
|
|
838
|
-
const response = await fetch('/logout', {
|
|
839
|
-
method: 'GET',
|
|
840
|
-
credentials: 'include',
|
|
841
|
-
});
|
|
842
|
-
|
|
843
|
-
if (response.status === 401) {
|
|
844
|
-
// Authentication cleared, reload page to trigger browser auth prompt
|
|
845
|
-
window.location.reload();
|
|
846
|
-
} else {
|
|
847
|
-
console.error('Logout failed');
|
|
848
|
-
alert('Logout failed. Please clear your browser cache and reload the page.');
|
|
849
|
-
}
|
|
850
|
-
} catch (error) {
|
|
851
|
-
console.error('Error during logout:', error);
|
|
852
|
-
alert('Error during logout. Please clear your browser cache and reload the page.');
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
// Initialization on page load
|
|
857
|
-
initializeForm();
|
|
858
|
-
</script>
|
|
859
|
-
</body>
|
|
860
|
-
</html>
|
|
861
|
-
`;
|
|
862
|
-
//# sourceMappingURL=html.js.map
|