mbkauthe 1.3.5 → 1.4.0
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 +249 -187
- package/docs/api.md +841 -0
- package/index.js +13 -2
- package/lib/main.js +104 -31
- package/lib/pool.js +8 -8
- package/lib/validateSessionAndRole.js +55 -29
- package/package.json +5 -5
- package/public/main.js +134 -0
- package/views/2fa.handlebars +35 -445
- package/views/Error/dError.handlebars +71 -551
- package/views/info.handlebars +180 -160
- package/views/loginmbkauthe.handlebars +37 -557
- package/views/sharedStyles.handlebars +498 -0
- package/views/showmessage.handlebars +97 -62
package/public/main.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
async function logout() {
|
|
2
|
+
const confirmation = confirm("Are you sure you want to logout?");
|
|
3
|
+
if (!confirmation) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
// Clear all caches before logging out (except rememberedUsername)
|
|
9
|
+
await nuclearCacheClear();
|
|
10
|
+
|
|
11
|
+
const response = await fetch("/mbkauthe/api/logout", {
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: {
|
|
14
|
+
"Content-Type": "application/json",
|
|
15
|
+
"Cache-Control": "no-cache"
|
|
16
|
+
},
|
|
17
|
+
credentials: "include"
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const result = await response.json();
|
|
21
|
+
|
|
22
|
+
if (response.ok) {
|
|
23
|
+
alert(result.message);
|
|
24
|
+
// Force a full page reload with cache bypass
|
|
25
|
+
window.location.href = window.location.origin;
|
|
26
|
+
} else {
|
|
27
|
+
alert(result.message);
|
|
28
|
+
}
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error("Error during logout:", error);
|
|
31
|
+
alert("Logout failed");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function nuclearCacheClear() {
|
|
36
|
+
try {
|
|
37
|
+
// Preserve rememberedUsername before clearing storage
|
|
38
|
+
const rememberedUsername = localStorage.getItem('rememberedUsername');
|
|
39
|
+
|
|
40
|
+
// 1. Clear all possible caches
|
|
41
|
+
if ('caches' in window) {
|
|
42
|
+
const cacheNames = await caches.keys();
|
|
43
|
+
await Promise.all(cacheNames.map(cacheName => caches.delete(cacheName)));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 2. Clear service workers
|
|
47
|
+
if ('serviceWorker' in navigator) {
|
|
48
|
+
const registrations = await navigator.serviceWorker.getRegistrations();
|
|
49
|
+
await Promise.all(registrations.map(registration => registration.unregister()));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 3. Clear all storage except rememberedUsername
|
|
53
|
+
localStorage.clear();
|
|
54
|
+
sessionStorage.clear();
|
|
55
|
+
if (rememberedUsername) {
|
|
56
|
+
localStorage.setItem('rememberedUsername', rememberedUsername);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if ('indexedDB' in window) {
|
|
60
|
+
try {
|
|
61
|
+
const dbs = await window.indexedDB.databases();
|
|
62
|
+
await Promise.all(dbs.map(db => {
|
|
63
|
+
if (db.name) {
|
|
64
|
+
return window.indexedDB.deleteDatabase(db.name);
|
|
65
|
+
}
|
|
66
|
+
return Promise.resolve();
|
|
67
|
+
}));
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error("Error clearing IndexedDB:", error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 4. Clear cookies (except those you want to preserve)
|
|
74
|
+
document.cookie.split(';').forEach(cookie => {
|
|
75
|
+
const eqPos = cookie.indexOf('=');
|
|
76
|
+
const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim();
|
|
77
|
+
|
|
78
|
+
// Skip cookies you want to preserve (add conditions as needed)
|
|
79
|
+
if (!name.startsWith('preserve_')) { // Example condition
|
|
80
|
+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${window.location.hostname}`;
|
|
81
|
+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${window.location.hostname}`;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// 5. Force hard reload with cache busting
|
|
86
|
+
window.location.reload();
|
|
87
|
+
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error('Nuclear cache clear failed:', error);
|
|
90
|
+
window.location.reload(true);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function logoutuser() {
|
|
95
|
+
await logout();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const validateSessionInterval = 60000;
|
|
99
|
+
// 1 minutes in milliseconds Function to check session validity by sending a request to the server
|
|
100
|
+
function checkSession() {
|
|
101
|
+
fetch("/api/validate-session")
|
|
102
|
+
.then((response) => {
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
// Redirect or handle errors (session expired, user inactive, etc.)
|
|
105
|
+
window.location.reload(); // Reload the page to update the session status
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
.catch((error) => console.error("Error checking session:", error));
|
|
109
|
+
}
|
|
110
|
+
// Call validateSession every 2 minutes (120000 milliseconds)
|
|
111
|
+
// setInterval(checkSession, validateSessionInterval);
|
|
112
|
+
|
|
113
|
+
function getCookieValue(cookieName) {
|
|
114
|
+
const cookies = document.cookie.split('; ');
|
|
115
|
+
for (let cookie of cookies) {
|
|
116
|
+
const [name, value] = cookie.split('=');
|
|
117
|
+
if (name === cookieName) {
|
|
118
|
+
return decodeURIComponent(value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null; // Return null if the cookie is not found
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function loadpage(url) {
|
|
125
|
+
window.location.href = url;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function formatDate(date) {
|
|
129
|
+
return new Date(date).toLocaleString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: true });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function reloadPage() {
|
|
133
|
+
window.location.reload();
|
|
134
|
+
}
|
package/views/2fa.handlebars
CHANGED
|
@@ -9,455 +9,28 @@
|
|
|
9
9
|
<meta name="keywords" content="MBK Tech Studio, Web-Portal, Web, Portal, Admin-Panel, Admin, login">
|
|
10
10
|
<meta property="og:title" content="Login | MBK Tech Studio" />
|
|
11
11
|
<meta property="og:image" content="https://www.mbktechstudio.com/Assets/Images/Icon/logo.png" />
|
|
12
|
-
<meta property="og:url" content="
|
|
13
|
-
<title>
|
|
12
|
+
<meta property="og:url" content="/mbkauthe/2fa">
|
|
13
|
+
<title>2FA | MBK Tech Studio Portal</title>
|
|
14
14
|
<link rel="icon" type="image/x-icon" href="https://mbktechstudio.com/Assets/Images/Icon/dgicon.svg">
|
|
15
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.
|
|
16
|
-
|
|
17
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
18
|
-
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
|
|
19
|
-
rel="stylesheet">
|
|
20
|
-
<style>
|
|
21
|
-
:root {
|
|
22
|
-
--primary: #4361ee;
|
|
23
|
-
--primary-dark: #3a0ca3;
|
|
24
|
-
--primary-light: rgba(67, 97, 238, 0.1);
|
|
25
|
-
--secondary: #f72585;
|
|
26
|
-
--secondary-light: rgba(247, 37, 133, 0.1);
|
|
27
|
-
--dark: #121212;
|
|
28
|
-
--dark-light: #1e1e1e;
|
|
29
|
-
--darker: #0a0a0a;
|
|
30
|
-
--light: #f8f9fa;
|
|
31
|
-
--lighter: #ffffff;
|
|
32
|
-
--gray: #cccccc;
|
|
33
|
-
--gray-dark: #888888;
|
|
34
|
-
--success: #4cc9f0;
|
|
35
|
-
--warning: #f8961e;
|
|
36
|
-
--danger: #ef233c;
|
|
37
|
-
--gradient: linear-gradient(135deg, var(--primary), var(--secondary));
|
|
38
|
-
--glass: rgba(30, 30, 30, 0.5);
|
|
39
|
-
--glass-border: rgba(255, 255, 255, 0.1);
|
|
40
|
-
--transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.1);
|
|
41
|
-
--shadow-sm: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
42
|
-
--shadow-md: 0 8px 30px rgba(0, 0, 0, 0.2);
|
|
43
|
-
--shadow-lg: 0 15px 40px rgba(0, 0, 0, 0.3);
|
|
44
|
-
--radius-sm: 8px;
|
|
45
|
-
--radius-md: 12px;
|
|
46
|
-
--radius-lg: 16px;
|
|
47
|
-
--radius-xl: 24px;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
* {
|
|
51
|
-
margin: 0;
|
|
52
|
-
padding: 0;
|
|
53
|
-
box-sizing: border-box;
|
|
54
|
-
font-family: 'Poppins', sans-serif;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
body {
|
|
58
|
-
background: var(--dark);
|
|
59
|
-
color: var(--light);
|
|
60
|
-
line-height: 1.6;
|
|
61
|
-
overflow-x: hidden;
|
|
62
|
-
min-height: 100vh;
|
|
63
|
-
display: flex;
|
|
64
|
-
flex-direction: column;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
header {
|
|
68
|
-
position: fixed;
|
|
69
|
-
top: 0;
|
|
70
|
-
left: 0;
|
|
71
|
-
width: 100%;
|
|
72
|
-
z-index: 1000;
|
|
73
|
-
transition: var(--transition);
|
|
74
|
-
background: linear-gradient(to bottom, rgba(10, 10, 10, 0.9), rgba(10, 10, 10, 0.7));
|
|
75
|
-
backdrop-filter: blur(10px);
|
|
76
|
-
border-bottom: 1px solid var(--glass-border);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
nav {
|
|
80
|
-
padding: 10px 5%;
|
|
81
|
-
max-width: 1400px;
|
|
82
|
-
margin: 0 auto;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.navbar {
|
|
86
|
-
display: flex;
|
|
87
|
-
justify-content: space-between;
|
|
88
|
-
align-items: center;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.logo {
|
|
92
|
-
display: flex;
|
|
93
|
-
align-items: center;
|
|
94
|
-
gap: 10px;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.logo img {
|
|
98
|
-
height: 30px;
|
|
99
|
-
width: auto;
|
|
100
|
-
transition: var(--transition);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.logo:hover img {
|
|
104
|
-
transform: rotate(15deg);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
.logo-text {
|
|
108
|
-
font-size: 1.8rem;
|
|
109
|
-
font-weight: 700;
|
|
110
|
-
background: var(--gradient);
|
|
111
|
-
-webkit-background-clip: text;
|
|
112
|
-
background-clip: text;
|
|
113
|
-
color: transparent;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.login-container {
|
|
117
|
-
flex: 1;
|
|
118
|
-
display: flex;
|
|
119
|
-
align-items: center;
|
|
120
|
-
justify-content: center;
|
|
121
|
-
padding: 120px 5% 80px;
|
|
122
|
-
position: relative;
|
|
123
|
-
overflow: hidden;
|
|
124
|
-
background: radial-gradient(circle at 70% 20%, rgba(67, 97, 238, 0.15), transparent 60%);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.login-box {
|
|
128
|
-
background: var(--dark-light);
|
|
129
|
-
border-radius: var(--radius-xl);
|
|
130
|
-
padding: 2rem;
|
|
131
|
-
width: 100%;
|
|
132
|
-
max-width: 500px;
|
|
133
|
-
box-shadow: var(--shadow-lg);
|
|
134
|
-
border: .125rem solid var(--glass-border);
|
|
135
|
-
position: relative;
|
|
136
|
-
z-index: 2;
|
|
137
|
-
transition: var(--transition);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.login-box:hover {
|
|
141
|
-
box-shadow: var(--shadow-lg);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.login-title {
|
|
145
|
-
text-align: center;
|
|
146
|
-
margin-bottom: 2rem;
|
|
147
|
-
font-size: 2rem;
|
|
148
|
-
position: relative;
|
|
149
|
-
color: var(--lighter);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
.login-title::after {
|
|
153
|
-
content: '';
|
|
154
|
-
position: absolute;
|
|
155
|
-
bottom: -10px;
|
|
156
|
-
left: 50%;
|
|
157
|
-
transform: translateX(-50%);
|
|
158
|
-
width: 80px;
|
|
159
|
-
height: 4px;
|
|
160
|
-
background: var(--gradient);
|
|
161
|
-
border-radius: 2px;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.form-group {
|
|
165
|
-
position: relative;
|
|
166
|
-
margin-bottom: 1rem;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
.form-input {
|
|
170
|
-
width: 100%;
|
|
171
|
-
padding: 12px 20px;
|
|
172
|
-
background: var(--darker);
|
|
173
|
-
border: 2px solid var(--glass-border);
|
|
174
|
-
border-radius: var(--radius-sm);
|
|
175
|
-
color: var(--light);
|
|
176
|
-
font-size: 1rem;
|
|
177
|
-
transition: var(--transition);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.form-input:focus {
|
|
181
|
-
outline: none;
|
|
182
|
-
border-color: var(--primary);
|
|
183
|
-
box-shadow: 0 0 0 3px var(--primary-light);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
.form-label {
|
|
187
|
-
position: absolute;
|
|
188
|
-
top: 15px;
|
|
189
|
-
left: 20px;
|
|
190
|
-
color: var(--gray);
|
|
191
|
-
transition: var(--transition);
|
|
192
|
-
pointer-events: none;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
.form-input:focus+.form-label,
|
|
196
|
-
.form-input:not(:placeholder-shown)+.form-label {
|
|
197
|
-
top: -10px;
|
|
198
|
-
left: 15px;
|
|
199
|
-
font-size: 0.8rem;
|
|
200
|
-
background: var(--dark-light);
|
|
201
|
-
padding: 0 5px;
|
|
202
|
-
color: var(--primary);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
.input-icon {
|
|
206
|
-
position: absolute;
|
|
207
|
-
right: 20px;
|
|
208
|
-
top: 50%;
|
|
209
|
-
transform: translateY(-50%);
|
|
210
|
-
color: var(--gray);
|
|
211
|
-
cursor: pointer;
|
|
212
|
-
transition: var(--transition);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
.input-icon:hover {
|
|
216
|
-
color: var(--primary);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
.btn-login {
|
|
220
|
-
width: 100%;
|
|
221
|
-
padding: 10px;
|
|
222
|
-
border-radius: var(--radius-sm);
|
|
223
|
-
background: var(--primary);
|
|
224
|
-
color: white;
|
|
225
|
-
font-weight: 600;
|
|
226
|
-
font-size: 1rem;
|
|
227
|
-
border: none;
|
|
228
|
-
cursor: pointer;
|
|
229
|
-
transition: var(--transition);
|
|
230
|
-
box-shadow: var(--shadow-sm);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
.btn-login:hover {
|
|
234
|
-
background: var(--primary-dark);
|
|
235
|
-
box-shadow: var(--shadow-md);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
.login-links {
|
|
239
|
-
display: flex;
|
|
240
|
-
justify-content: space-between;
|
|
241
|
-
margin-top: 1.5rem;
|
|
242
|
-
font-size: 0.9rem;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
.login-link {
|
|
246
|
-
color: var(--gray);
|
|
247
|
-
transition: var(--transition);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
.login-link:hover {
|
|
251
|
-
color: var(--primary);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
.terms-info {
|
|
255
|
-
margin-top: 1rem;
|
|
256
|
-
font-size: 0.8rem;
|
|
257
|
-
color: var(--gray);
|
|
258
|
-
text-align: center;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
.terms-link {
|
|
262
|
-
color: var(--primary);
|
|
263
|
-
font-weight: 500;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
.token-container {
|
|
267
|
-
animation: fadeInUp 0.4s ease-out;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
.token-container.enable {
|
|
271
|
-
display: block;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
.ai-element {
|
|
275
|
-
position: absolute;
|
|
276
|
-
opacity: 0.1;
|
|
277
|
-
z-index: 1;
|
|
278
|
-
animation: float 6s ease-in-out infinite;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.ai-element:nth-child(1) {
|
|
282
|
-
top: 20%;
|
|
283
|
-
left: 10%;
|
|
284
|
-
font-size: 5rem;
|
|
285
|
-
animation-delay: 0s;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
.ai-element:nth-child(2) {
|
|
289
|
-
top: 60%;
|
|
290
|
-
left: 80%;
|
|
291
|
-
font-size: 4rem;
|
|
292
|
-
animation-delay: 1s;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.ai-element:nth-child(3) {
|
|
296
|
-
top: 30%;
|
|
297
|
-
left: 70%;
|
|
298
|
-
font-size: 3rem;
|
|
299
|
-
animation-delay: 2s;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
.ai-element:nth-child(4) {
|
|
303
|
-
top: 80%;
|
|
304
|
-
left: 20%;
|
|
305
|
-
font-size: 6rem;
|
|
306
|
-
animation-delay: 3s;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
@keyframes float {
|
|
310
|
-
|
|
311
|
-
0%,
|
|
312
|
-
100% {
|
|
313
|
-
transform: translateY(0) rotate(0deg);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
50% {
|
|
317
|
-
transform: translateY(-20px) rotate(5deg);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
@keyframes fadeInUp {
|
|
322
|
-
from {
|
|
323
|
-
opacity: 0;
|
|
324
|
-
transform: translateY(20px);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
to {
|
|
328
|
-
opacity: 1;
|
|
329
|
-
transform: translateY(0);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
@media (max-width: 768px) {
|
|
334
|
-
.login-box {
|
|
335
|
-
padding: 2rem;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
.login-title {
|
|
339
|
-
font-size: 1.8rem;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
.version-info {
|
|
343
|
-
bottom: 10px;
|
|
344
|
-
right: 10px;
|
|
345
|
-
font-size: 0.7rem;
|
|
346
|
-
padding: 6px 10px;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
@media (max-width: 576px) {
|
|
351
|
-
.login-box {
|
|
352
|
-
padding: 1.5rem;
|
|
353
|
-
border-radius: var(--radius-lg);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
.login-links {
|
|
357
|
-
flex-direction: column;
|
|
358
|
-
gap: 0.5rem;
|
|
359
|
-
align-items: center;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
.remember-me {
|
|
364
|
-
display: flex;
|
|
365
|
-
align-items: center;
|
|
366
|
-
justify-content: center;
|
|
367
|
-
width: 100%;
|
|
368
|
-
margin: 1rem 0;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
.remember-me input[type="checkbox"] {
|
|
372
|
-
appearance: none;
|
|
373
|
-
-webkit-appearance: none;
|
|
374
|
-
width: 18px;
|
|
375
|
-
height: 18px;
|
|
376
|
-
border: 2px solid var(--glass-border);
|
|
377
|
-
border-radius: var(--radius-sm);
|
|
378
|
-
margin-right: 10px;
|
|
379
|
-
cursor: pointer;
|
|
380
|
-
position: relative;
|
|
381
|
-
transition: var(--transition);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
.remember-me input[type="checkbox"]:checked {
|
|
385
|
-
background-color: var(--primary);
|
|
386
|
-
border-color: var(--primary);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
.remember-me input[type="checkbox"]:checked::after {
|
|
390
|
-
content: '\f00c';
|
|
391
|
-
font-family: 'Font Awesome 6 Free';
|
|
392
|
-
font-weight: 900;
|
|
393
|
-
position: absolute;
|
|
394
|
-
top: 50%;
|
|
395
|
-
left: 50%;
|
|
396
|
-
transform: translate(-50%, -50%);
|
|
397
|
-
color: white;
|
|
398
|
-
font-size: 10px;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
.remember-me label {
|
|
402
|
-
color: var(--gray);
|
|
403
|
-
cursor: pointer;
|
|
404
|
-
transition: var(--transition);
|
|
405
|
-
font-size: 0.9rem;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.remember-me label:hover {
|
|
409
|
-
color: var(--light);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.WarningboxInfo {
|
|
413
|
-
background: var(--dark-light);
|
|
414
|
-
border: 0.5px solid var(--warning);
|
|
415
|
-
border-left: 4px solid var(--warning);
|
|
416
|
-
padding: 0.75rem 1rem;
|
|
417
|
-
border-radius: var(--radius-sm);
|
|
418
|
-
color: var(--warning);
|
|
419
|
-
font-size: 0.9rem;
|
|
420
|
-
font-weight: 500;
|
|
421
|
-
margin-top: 1rem;
|
|
422
|
-
text-align: center;
|
|
423
|
-
box-shadow: var(--shadow-sm);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
.logo-comp {
|
|
427
|
-
font-size: 1rem;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
.version-info {
|
|
431
|
-
position: fixed;
|
|
432
|
-
bottom: 20px;
|
|
433
|
-
right: 20px;
|
|
434
|
-
background: var(--dark-light);
|
|
435
|
-
color: var(--gray);
|
|
436
|
-
padding: 8px 12px;
|
|
437
|
-
border-radius: var(--radius-sm);
|
|
438
|
-
font-size: 0.75rem;
|
|
439
|
-
border: 1px solid var(--glass-border);
|
|
440
|
-
z-index: 999;
|
|
441
|
-
transition: var(--transition);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
.version-info:hover {
|
|
445
|
-
color: var(--primary);
|
|
446
|
-
border-color: var(--primary);
|
|
447
|
-
}
|
|
448
|
-
</style>
|
|
15
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
16
|
+
{{> sharedStyles}}
|
|
449
17
|
</head>
|
|
450
18
|
|
|
451
19
|
<body>
|
|
452
20
|
<header>
|
|
453
|
-
<
|
|
454
|
-
<
|
|
455
|
-
<
|
|
456
|
-
<
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
21
|
+
<div class="header-container">
|
|
22
|
+
<a class="logo">
|
|
23
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 90" class="iconAboveSlogan">
|
|
24
|
+
<g id="8db2a7f9-6efc-4f7e-ae5b-8ba33875da43" transform="matrix(2.8125,0,0,2.8125,0,0)" stroke="none"
|
|
25
|
+
fill="#00b894">
|
|
26
|
+
<path
|
|
27
|
+
d="M0 32h32V0H0v32zm19.377-19.492l6.936-6.936v20.855h-6.936V12.508zM5.688 5.572l6.936 6.936v13.919H5.688V5.572z">
|
|
28
|
+
</path>
|
|
29
|
+
</g>
|
|
30
|
+
</svg>
|
|
31
|
+
<span class="logo-text">{{appName}} <span class="logo-comp">MBKTECHStudio</span></span>
|
|
32
|
+
</a>
|
|
33
|
+
</div>
|
|
461
34
|
</header>
|
|
462
35
|
|
|
463
36
|
{{> showmessage}}
|
|
@@ -506,9 +79,20 @@
|
|
|
506
79
|
</div>
|
|
507
80
|
|
|
508
81
|
<script>
|
|
82
|
+
function tokeninfo() {
|
|
83
|
+
showMessage(`The 2FA token is a 6-digit code generated by your authenticator app (such as Google Authenticator, Microsoft Authenticator, or Authy). Enter the code shown in your app to complete login. If you have not set up 2FA or are having trouble, please contact support.`, `What is the 2FA token?`);
|
|
84
|
+
}
|
|
85
|
+
|
|
509
86
|
document.getElementById('loginForm').addEventListener('submit', async (e) => {
|
|
510
87
|
e.preventDefault();
|
|
511
88
|
const token = document.getElementById('token').value;
|
|
89
|
+
const csrfToken = document.querySelector('input[name="_csrf"]').value;
|
|
90
|
+
const loginButton = document.getElementById('loginButton');
|
|
91
|
+
const loginButtonText = document.getElementById('loginButtonText');
|
|
92
|
+
|
|
93
|
+
loginButton.disabled = true;
|
|
94
|
+
loginButtonText.textContent = 'Verifying...';
|
|
95
|
+
|
|
512
96
|
try {
|
|
513
97
|
const response = await fetch('/mbkauthe/api/verify-2fa', {
|
|
514
98
|
method: 'POST',
|
|
@@ -516,16 +100,22 @@
|
|
|
516
100
|
'Content-Type': 'application/json'
|
|
517
101
|
},
|
|
518
102
|
body: JSON.stringify({
|
|
519
|
-
token
|
|
103
|
+
token,
|
|
104
|
+
_csrf: csrfToken
|
|
520
105
|
})
|
|
521
106
|
});
|
|
522
107
|
const data = await response.json();
|
|
523
108
|
if (data.success) {
|
|
109
|
+
loginButtonText.textContent = 'Success! Redirecting...';
|
|
524
110
|
window.location.href = data.redirectUrl || '{{{ customURL }}}';
|
|
525
111
|
} else {
|
|
112
|
+
loginButton.disabled = false;
|
|
113
|
+
loginButtonText.textContent = 'Verify';
|
|
526
114
|
showMessage(data.message, 'Error');
|
|
527
115
|
}
|
|
528
116
|
} catch (error) {
|
|
117
|
+
loginButton.disabled = false;
|
|
118
|
+
loginButtonText.textContent = 'Verify';
|
|
529
119
|
showMessage('Failed to verify token. Please try again.', 'Error');
|
|
530
120
|
}
|
|
531
121
|
});
|