senku21230 commited on
Commit
00b0aae
·
verified ·
1 Parent(s): 81ef6db

Upload 3 files

Browse files
Files changed (3) hide show
  1. login.html +533 -0
  2. package.json +14 -0
  3. server.js +55 -0
login.html ADDED
@@ -0,0 +1,533 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>Secure Terminal Access</title>
7
+
8
+ <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
9
+
10
+ <style>
11
+ /* --- CORE VARIABLES --- */
12
+ :root {
13
+ --bg-deep: #0a0b10;
14
+ --bg-surface: #12141d;
15
+ --bg-card: rgba(22, 24, 34, 0.6);
16
+ --brand-orange: #FF6B00;
17
+ --brand-orange-light: #FFA600;
18
+ --brand-glow: rgba(255, 107, 0, 0.4);
19
+ --text-primary: #F8F9FA;
20
+ --text-secondary: #8B949E;
21
+ --input-bg: rgba(10, 11, 16, 0.8);
22
+ --border-color: rgba(255, 255, 255, 0.06);
23
+ --border-focus: rgba(255, 107, 0, 0.5);
24
+ --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
25
+ --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
26
+ }
27
+
28
+ /* --- RESET & BASE --- */
29
+ * {
30
+ margin: 0;
31
+ padding: 0;
32
+ box-sizing: border-box;
33
+ -webkit-tap-highlight-color: transparent;
34
+ }
35
+
36
+ body {
37
+ font-family: 'Outfit', sans-serif;
38
+ background-color: var(--bg-deep);
39
+ color: var(--text-primary);
40
+ min-height: 100vh;
41
+ display: flex;
42
+ justify-content: center;
43
+ align-items: center;
44
+ overflow: hidden;
45
+ position: relative;
46
+ }
47
+
48
+ /* --- DYNAMIC BACKGROUND & GRID --- */
49
+ .bg-grid {
50
+ position: absolute;
51
+ top: 0; left: 0; width: 100vw; height: 100vh;
52
+ background-image:
53
+ linear-gradient(to right, rgba(255,255,255,0.02) 1px, transparent 1px),
54
+ linear-gradient(to bottom, rgba(255,255,255,0.02) 1px, transparent 1px);
55
+ background-size: 40px 40px;
56
+ z-index: 0;
57
+ transform: perspective(500px) rotateX(60deg) translateY(-100px) translateZ(-200px);
58
+ animation: gridMove 20s linear infinite;
59
+ opacity: 0.5;
60
+ }
61
+
62
+ .ambient-light {
63
+ position: absolute;
64
+ top: 50%;
65
+ left: 50%;
66
+ transform: translate(-50%, -50%);
67
+ width: 500px;
68
+ height: 500px;
69
+ background: radial-gradient(circle, var(--brand-glow) 0%, transparent 60%);
70
+ filter: blur(80px);
71
+ z-index: 1;
72
+ animation: pulseLight 8s alternate infinite;
73
+ }
74
+
75
+ /* --- APP LAYOUT --- */
76
+ .app-container {
77
+ width: 100%;
78
+ max-width: 440px;
79
+ position: relative;
80
+ z-index: 10;
81
+ padding: 24px;
82
+ }
83
+
84
+ /* --- MAIN LOGIN CARD --- */
85
+ .login-card {
86
+ background: var(--bg-card);
87
+ border-radius: 28px;
88
+ padding: 45px 35px;
89
+ backdrop-filter: blur(20px);
90
+ -webkit-backdrop-filter: blur(20px);
91
+ border: 1px solid var(--border-color);
92
+ box-shadow: 0 30px 60px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.05);
93
+ position: relative;
94
+ transform: translateY(30px);
95
+ opacity: 0;
96
+ animation: cardReveal 1s var(--ease-out-expo) forwards;
97
+ }
98
+
99
+ .login-card::before {
100
+ content: '';
101
+ position: absolute;
102
+ top: -1px; left: -1px; right: -1px; bottom: -1px;
103
+ border-radius: 28px;
104
+ background: linear-gradient(135deg, var(--brand-orange-light), transparent 40%, transparent 60%, var(--brand-orange));
105
+ z-index: -1;
106
+ opacity: 0;
107
+ transition: opacity 0.5s ease;
108
+ mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
109
+ -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
110
+ -webkit-mask-composite: xor;
111
+ mask-composite: exclude;
112
+ padding: 1px;
113
+ }
114
+
115
+ .login-card:hover::before {
116
+ opacity: 0.5;
117
+ }
118
+
119
+ /* --- ADVANCED SVG LOGO --- */
120
+ .logo-wrapper {
121
+ display: flex;
122
+ justify-content: center;
123
+ margin-bottom: 35px;
124
+ position: relative;
125
+ }
126
+
127
+ .logo-core {
128
+ position: relative;
129
+ width: 85px;
130
+ height: 85px;
131
+ display: flex;
132
+ justify-content: center;
133
+ align-items: center;
134
+ animation: float 6s ease-in-out infinite;
135
+ }
136
+
137
+ .logo-svg {
138
+ width: 100%;
139
+ height: 100%;
140
+ filter: drop-shadow(0 0 15px var(--brand-glow));
141
+ }
142
+
143
+ .outer-hex {
144
+ transform-origin: center;
145
+ animation: spinRotate 20s linear infinite;
146
+ }
147
+ .inner-dash {
148
+ stroke-dasharray: 10 5;
149
+ animation: dashMove 2s linear infinite;
150
+ }
151
+
152
+ /* --- TYPOGRAPHY --- */
153
+ .header-section {
154
+ text-align: center;
155
+ margin-bottom: 40px;
156
+ }
157
+
158
+ h1 {
159
+ font-size: 26px;
160
+ font-weight: 600;
161
+ letter-spacing: -0.5px;
162
+ margin-bottom: 12px;
163
+ background: linear-gradient(to right, #FFF, #A0A5B0);
164
+ -webkit-background-clip: text;
165
+ -webkit-text-fill-color: transparent;
166
+ }
167
+
168
+ p {
169
+ font-size: 15px;
170
+ color: var(--text-secondary);
171
+ font-weight: 400;
172
+ }
173
+
174
+ /* --- FORM & INPUTS --- */
175
+ .form-group {
176
+ position: relative;
177
+ margin-bottom: 30px;
178
+ }
179
+
180
+ .input-icon, .toggle-icon {
181
+ position: absolute;
182
+ top: 50%;
183
+ transform: translateY(-50%);
184
+ color: var(--text-secondary);
185
+ transition: all 0.3s ease;
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: center;
189
+ }
190
+
191
+ .input-icon {
192
+ left: 18px;
193
+ }
194
+
195
+ .toggle-icon {
196
+ right: 18px;
197
+ cursor: pointer;
198
+ background: none;
199
+ border: none;
200
+ padding: 5px;
201
+ }
202
+
203
+ .toggle-icon:hover {
204
+ color: var(--text-primary);
205
+ }
206
+
207
+ .secure-input {
208
+ width: 100%;
209
+ background: var(--input-bg);
210
+ border: 1.5px solid var(--border-color);
211
+ border-radius: 16px;
212
+ padding: 20px 55px 20px 50px;
213
+ color: var(--brand-orange-light);
214
+ font-family: 'JetBrains Mono', monospace;
215
+ font-size: 16px;
216
+ letter-spacing: 2px;
217
+ outline: none;
218
+ transition: all 0.3s var(--ease-out-expo);
219
+ box-shadow: inset 0 2px 10px rgba(0,0,0,0.5);
220
+ }
221
+
222
+ .secure-input::placeholder {
223
+ color: rgba(139, 148, 158, 0.5);
224
+ font-family: 'Outfit', sans-serif;
225
+ letter-spacing: normal;
226
+ }
227
+
228
+ .secure-input:focus {
229
+ border-color: var(--brand-orange);
230
+ background: rgba(10, 11, 16, 0.95);
231
+ box-shadow: 0 0 0 4px rgba(255, 107, 0, 0.1), inset 0 2px 10px rgba(0,0,0,0.5);
232
+ }
233
+
234
+ .secure-input:focus ~ .input-icon {
235
+ color: var(--brand-orange);
236
+ filter: drop-shadow(0 0 5px var(--brand-glow));
237
+ }
238
+
239
+ /* --- SUBMIT BUTTON --- */
240
+ .btn-connect {
241
+ width: 100%;
242
+ background: linear-gradient(135deg, var(--brand-orange) 0%, #D85A00 100%);
243
+ color: #fff;
244
+ border: none;
245
+ border-radius: 16px;
246
+ padding: 20px;
247
+ font-size: 17px;
248
+ font-weight: 600;
249
+ font-family: 'Outfit', sans-serif;
250
+ cursor: pointer;
251
+ position: relative;
252
+ overflow: hidden;
253
+ transition: all 0.3s ease;
254
+ box-shadow: 0 10px 25px rgba(255, 107, 0, 0.3);
255
+ display: flex;
256
+ justify-content: center;
257
+ align-items: center;
258
+ gap: 12px;
259
+ }
260
+
261
+ .btn-connect::after {
262
+ content: '';
263
+ position: absolute;
264
+ top: 0; left: -100%;
265
+ width: 50%; height: 100%;
266
+ background: linear-gradient(to right, transparent, rgba(255,255,255,0.2), transparent);
267
+ transform: skewX(-25deg);
268
+ transition: all 0.5s ease;
269
+ }
270
+
271
+ .btn-connect:hover {
272
+ transform: translateY(-2px);
273
+ box-shadow: 0 15px 35px rgba(255, 107, 0, 0.4);
274
+ background: linear-gradient(135deg, var(--brand-orange-light) 0%, var(--brand-orange) 100%);
275
+ }
276
+
277
+ .btn-connect:hover::after {
278
+ left: 200%;
279
+ }
280
+
281
+ .btn-connect:active {
282
+ transform: translateY(1px);
283
+ box-shadow: 0 5px 15px rgba(255, 107, 0, 0.3);
284
+ }
285
+
286
+ .loader-ring {
287
+ display: none;
288
+ width: 24px; height: 24px;
289
+ border: 3px solid rgba(255,255,255,0.2);
290
+ border-top: 3px solid #fff;
291
+ border-radius: 50%;
292
+ animation: spinRotate 0.8s linear infinite;
293
+ }
294
+
295
+ .btn-connect.is-loading .btn-text { display: none; }
296
+ .btn-connect.is-loading .loader-ring { display: block; }
297
+ .btn-connect.is-loading {
298
+ pointer-events: none;
299
+ opacity: 0.9;
300
+ }
301
+
302
+ /* --- SUCCESS OVERLAY --- */
303
+ .auth-success {
304
+ position: absolute;
305
+ top: 0; left: 0; width: 100%; height: 100%;
306
+ background: rgba(18, 20, 29, 0.95);
307
+ backdrop-filter: blur(10px);
308
+ border-radius: 28px;
309
+ display: flex;
310
+ flex-direction: column;
311
+ align-items: center;
312
+ justify-content: center;
313
+ opacity: 0;
314
+ pointer-events: none;
315
+ transition: all 0.4s ease;
316
+ z-index: 20;
317
+ }
318
+
319
+ .auth-success.active {
320
+ opacity: 1;
321
+ pointer-events: all;
322
+ }
323
+
324
+ .shield-check {
325
+ width: 75px;
326
+ height: 75px;
327
+ color: #10B981;
328
+ margin-bottom: 25px;
329
+ stroke-dasharray: 100;
330
+ stroke-dashoffset: 100;
331
+ filter: drop-shadow(0 0 15px rgba(16, 185, 129, 0.4));
332
+ }
333
+
334
+ .auth-success.active .shield-check {
335
+ animation: drawCheck 1s var(--ease-out-expo) forwards;
336
+ animation-delay: 0.2s;
337
+ }
338
+
339
+ .success-msg {
340
+ color: #10B981;
341
+ font-size: 22px;
342
+ font-weight: 600;
343
+ letter-spacing: 1.5px;
344
+ opacity: 0;
345
+ transform: translateY(10px);
346
+ }
347
+
348
+ .auth-success.active .success-msg {
349
+ animation: slideUpFade 0.5s ease forwards;
350
+ animation-delay: 0.6s;
351
+ }
352
+
353
+ /* --- KEYFRAMES --- */
354
+ @keyframes gridMove {
355
+ 0% { background-position: 0 0; }
356
+ 100% { background-position: 0 40px; }
357
+ }
358
+ @keyframes pulseLight {
359
+ 0% { opacity: 0.4; transform: translate(-50%, -50%) scale(1); }
360
+ 100% { opacity: 0.7; transform: translate(-50%, -50%) scale(1.1); }
361
+ }
362
+ @keyframes cardReveal {
363
+ to { opacity: 1; transform: translateY(0); }
364
+ }
365
+ @keyframes float {
366
+ 0%, 100% { transform: translateY(0); }
367
+ 50% { transform: translateY(-10px); }
368
+ }
369
+ @keyframes spinRotate {
370
+ to { transform: rotate(360deg); }
371
+ }
372
+ @keyframes dashMove {
373
+ to { stroke-dashoffset: -15; }
374
+ }
375
+ @keyframes drawCheck {
376
+ to { stroke-dashoffset: 0; }
377
+ }
378
+ @keyframes slideUpFade {
379
+ to { opacity: 1; transform: translateY(0); }
380
+ }
381
+ </style>
382
+ </head>
383
+ <body>
384
+
385
+ <div class="bg-grid"></div>
386
+ <div class="ambient-light"></div>
387
+
388
+ <div class="app-container">
389
+
390
+ <div class="login-card">
391
+
392
+ <div class="logo-wrapper">
393
+ <div class="logo-core">
394
+ <svg class="logo-svg" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
395
+ <defs>
396
+ <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
397
+ <stop offset="0%" stop-color="#FFA600" />
398
+ <stop offset="100%" stop-color="#FF6B00" />
399
+ </linearGradient>
400
+ </defs>
401
+
402
+ <g class="outer-hex">
403
+ <path d="M50 2L91.569 26V74L50 98L8.431 74V26L50 2Z" stroke="url(#primaryGrad)" stroke-width="2" stroke-opacity="0.3"/>
404
+ <path d="M50 8L86.373 29V71L50 92L13.627 71V29L50 8Z" stroke="url(#primaryGrad)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" class="inner-dash"/>
405
+ </g>
406
+
407
+ <path d="M50 22L70 34V66L50 78L30 66V34L50 22Z" fill="rgba(255, 107, 0, 0.1)" stroke="url(#primaryGrad)" stroke-width="2"/>
408
+
409
+ <path d="M45 40L55 50L45 60" stroke="url(#primaryGrad)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
410
+ </svg>
411
+ </div>
412
+ </div>
413
+
414
+ <div class="header-section">
415
+ <h1>Secure Terminal Access</h1>
416
+ <p>Please authenticate to continue</p>
417
+ </div>
418
+
419
+ <form id="terminalForm">
420
+ <div class="form-group">
421
+ <div class="input-icon">
422
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
423
+ <path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path>
424
+ </svg>
425
+ </div>
426
+
427
+ <input type="password" id="secretKey" class="secure-input" placeholder="Enter Security Key" required autocomplete="off">
428
+
429
+ <button type="button" class="toggle-icon" id="togglePassword">
430
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="eyeIconSVG">
431
+ <path class="eye-path" d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
432
+ <circle class="eye-circle" cx="12" cy="12" r="3"></circle>
433
+ <line class="eye-slash" x1="1" y1="1" x2="23" y2="23" style="display:none;"></line>
434
+ </svg>
435
+ </button>
436
+ </div>
437
+
438
+ <button type="submit" class="btn-connect" id="connectBtn">
439
+ <span class="btn-text" id="btnText">Connect to Terminal</span>
440
+ <div class="loader-ring"></div>
441
+ </button>
442
+ </form>
443
+
444
+ <div class="auth-success" id="successScreen">
445
+ <svg class="shield-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
446
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
447
+ <polyline points="9 12 11 14 15 10"></polyline>
448
+ </svg>
449
+ <div class="success-msg">ACCESS GRANTED</div>
450
+ </div>
451
+
452
+ </div>
453
+ </div>
454
+
455
+ <script>
456
+ document.addEventListener('DOMContentLoaded', () => {
457
+ const form = document.getElementById('terminalForm');
458
+ const keyInput = document.getElementById('secretKey');
459
+ const toggleBtn = document.getElementById('togglePassword');
460
+ const eyeSlash = document.querySelector('.eye-slash');
461
+ const connectBtn = document.getElementById('connectBtn');
462
+ const btnText = document.getElementById('btnText');
463
+ const successScreen = document.getElementById('successScreen');
464
+
465
+ // Password Visibility Toggle Logic
466
+ toggleBtn.addEventListener('click', () => {
467
+ if (keyInput.type === 'password') {
468
+ keyInput.type = 'text';
469
+ eyeSlash.style.display = 'block';
470
+ toggleBtn.style.color = 'var(--brand-orange)';
471
+ } else {
472
+ keyInput.type = 'password';
473
+ eyeSlash.style.display = 'none';
474
+ toggleBtn.style.color = 'var(--text-secondary)';
475
+ }
476
+ });
477
+
478
+ // Real Backend Form Submit Handling
479
+ form.addEventListener('submit', async (e) => {
480
+ e.preventDefault();
481
+ const keyValue = keyInput.value.trim();
482
+
483
+ if(!keyValue) return;
484
+
485
+ // Start Loading State
486
+ connectBtn.classList.add('is-loading');
487
+ keyInput.disabled = true;
488
+
489
+ try {
490
+ // Send password to backend
491
+ const response = await fetch('/login', {
492
+ method: 'POST',
493
+ headers: {
494
+ 'Content-Type': 'application/x-www-form-urlencoded',
495
+ },
496
+ body: `password=${encodeURIComponent(keyValue)}`
497
+ });
498
+
499
+ connectBtn.classList.remove('is-loading');
500
+
501
+ // Check response status
502
+ if (response.url.endsWith('/login?error=1')) {
503
+ // Error State
504
+ keyInput.disabled = false;
505
+ keyInput.style.borderColor = '#ef4444';
506
+ btnText.textContent = "Invalid Key! Try Again";
507
+ btnText.style.color = '#ef4444';
508
+
509
+ setTimeout(() => {
510
+ keyInput.style.borderColor = 'var(--border-color)';
511
+ btnText.textContent = "Connect to Terminal";
512
+ btnText.style.color = '#fff';
513
+ }, 2500);
514
+
515
+ } else {
516
+ // Success State
517
+ successScreen.classList.add('active');
518
+
519
+ setTimeout(() => {
520
+ window.location.href = '/';
521
+ }, 1500);
522
+ }
523
+ } catch (error) {
524
+ console.error("Connection failed", error);
525
+ connectBtn.classList.remove('is-loading');
526
+ keyInput.disabled = false;
527
+ }
528
+ });
529
+ });
530
+ </script>
531
+
532
+ </body>
533
+ </html>
package.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "secure-terminal",
3
+ "version": "1.0.0",
4
+ "description": "Custom Proxy for ttyd",
5
+ "main": "server.js",
6
+ "scripts": {
7
+ "start": "node server.js"
8
+ },
9
+ "dependencies": {
10
+ "cookie-parser": "^1.4.6",
11
+ "express": "^4.18.2",
12
+ "http-proxy-middleware": "^2.0.6"
13
+ }
14
+ }
server.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require('express');
2
+ const { createProxyMiddleware } = require('http-proxy-middleware');
3
+ const cookieParser = require('cookie-parser');
4
+ const path = require('path');
5
+
6
+ const app = express();
7
+ app.use(express.urlencoded({ extended: true }));
8
+ app.use(cookieParser());
9
+
10
+ // Hugging Face Secret থেকে পাসওয়ার্ড নেওয়া হচ্ছে
11
+ const SECRET_PASSWORD = process.env.TERMINAL_PASSWORD || 'ayon123';
12
+
13
+ // লগইন পেজ রেন্ডার করা
14
+ app.get('/login', (req, res) => {
15
+ res.sendFile(path.join(__dirname, 'login.html'));
16
+ });
17
+
18
+ // পাসওয়ার্ড ভেরিফিকেশন এবং লগ ট্র্যাকিং
19
+ app.post('/login', (req, res) => {
20
+ if (req.body.password === SECRET_PASSWORD) {
21
+ console.log('🔐 [AUTH] Desktop access granted. Welcome User!');
22
+ res.cookie('auth_token', 'secure_session_active', { httpOnly: true, maxAge: 24 * 60 * 60 * 1000 });
23
+ res.redirect('/');
24
+ } else {
25
+ console.log('⚠️ [AUTH] Failed desktop login attempt! Invalid key.');
26
+ res.redirect('/login?error=1');
27
+ }
28
+ });
29
+
30
+ // সিকিউরিটি চেক মিডলওয়্যার
31
+ const checkAuth = (req, res, next) => {
32
+ if (req.cookies.auth_token === 'secure_session_active') {
33
+ next();
34
+ } else {
35
+ res.redirect('/login');
36
+ }
37
+ };
38
+
39
+ // NoVNC ডেস্কটপ স্ক্রিনের সাথে কানেকশন প্রক্সি করা
40
+ const desktopProxy = createProxyMiddleware({
41
+ target: 'http://127.0.0.1:8080',
42
+ ws: true,
43
+ changeOrigin: true,
44
+ logLevel: 'silent'
45
+ });
46
+
47
+ // মূল রাউটে প্রক্সি যুক্ত করা
48
+ app.use('/', checkAuth, desktopProxy);
49
+
50
+ // Hugging Face-এর মূল পোর্টে সার্ভার রান করা
51
+ app.listen(7860, () => {
52
+ console.log('\n===================================================');
53
+ console.log('🖥️ UBUNTU GUI & SECURE PROXY ENGINE RUNNING 🖥️');
54
+ console.log('===================================================\n');
55
+ });