|
201
|
1 <!DOCTYPE html>
|
|
|
2 <html lang="en">
|
|
|
3 <head>
|
|
|
4 {{/parts/base_head.html}}
|
|
|
5 <title>Login | Notes</title>
|
|
|
6 <style>
|
|
|
7 .login-page {
|
|
|
8 max-width: 400px;
|
|
|
9 margin: 100px auto;
|
|
|
10 padding: 20px;
|
|
|
11 }
|
|
|
12 .login-box {
|
|
|
13 background: #fff;
|
|
|
14 border: 1px solid #ddd;
|
|
|
15 border-radius: 8px;
|
|
|
16 padding: 32px;
|
|
|
17 box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
|
18 }
|
|
|
19 .login-box h1 {
|
|
|
20 margin: 0 0 24px 0;
|
|
|
21 font-size: 24px;
|
|
|
22 text-align: center;
|
|
|
23 }
|
|
|
24 .login-box label {
|
|
|
25 display: block;
|
|
|
26 margin-bottom: 8px;
|
|
|
27 font-weight: 500;
|
|
|
28 }
|
|
|
29 .login-box input {
|
|
|
30 width: 100%;
|
|
|
31 padding: 12px;
|
|
|
32 border: 1px solid #ccc;
|
|
|
33 border-radius: 4px;
|
|
|
34 font-size: 16px;
|
|
|
35 box-sizing: border-box;
|
|
|
36 }
|
|
|
37 .login-box input:focus {
|
|
|
38 outline: none;
|
|
|
39 border-color: #0078ff;
|
|
|
40 }
|
|
|
41 .login-box button {
|
|
|
42 width: 100%;
|
|
|
43 padding: 12px;
|
|
|
44 margin-top: 16px;
|
|
|
45 background: #0078ff;
|
|
|
46 color: white;
|
|
|
47 border: none;
|
|
|
48 border-radius: 4px;
|
|
|
49 font-size: 16px;
|
|
|
50 cursor: pointer;
|
|
|
51 }
|
|
|
52 .login-box button:hover {
|
|
|
53 background: #0066dd;
|
|
|
54 }
|
|
|
55 .error-msg {
|
|
|
56 color: #d32f2f;
|
|
|
57 margin-top: 12px;
|
|
|
58 text-align: center;
|
|
|
59 display: none;
|
|
|
60 }
|
|
|
61 </style>
|
|
|
62 </head>
|
|
|
63 <body>
|
|
|
64 {{/parts/header.html}}
|
|
|
65
|
|
|
66 <main class="login-page">
|
|
|
67 <div class="login-box">
|
|
|
68 <h1>Notes Login</h1>
|
|
|
69 <form id="login-form">
|
|
|
70 <label for="token">Access Token</label>
|
|
|
71 <input type="password" id="token" placeholder="Enter your access token" required>
|
|
|
72 <button type="submit">Login</button>
|
|
|
73 <p class="error-msg" id="error-msg">Invalid token</p>
|
|
|
74 </form>
|
|
|
75 </div>
|
|
|
76 </main>
|
|
|
77
|
|
|
78 {{/parts/footer.html}}
|
|
|
79
|
|
|
80 <script>
|
|
|
81 // Check if already logged in
|
|
|
82 const savedToken = localStorage.getItem('notes-auth-token');
|
|
|
83 if (savedToken) {
|
|
|
84 window.location.href = '/notes/';
|
|
|
85 }
|
|
|
86
|
|
|
87 document.getElementById('login-form').addEventListener('submit', async function(e) {
|
|
|
88 e.preventDefault();
|
|
|
89
|
|
|
90 const token = document.getElementById('token').value.trim();
|
|
|
91 if (!token) return;
|
|
|
92
|
|
|
93 // Verify token by trying to load a document
|
|
|
94 try {
|
|
|
95 const response = await fetch('/api/editor/load/index', {
|
|
|
96 headers: { 'Authorization': 'Bearer ' + token }
|
|
|
97 });
|
|
|
98
|
|
|
99 if (response.ok) {
|
|
|
100 localStorage.setItem('notes-auth-token', token);
|
|
|
101 // Redirect to originally requested page or /notes/
|
|
|
102 const returnUrl = new URLSearchParams(window.location.search).get('return') || '/notes/';
|
|
|
103 window.location.href = returnUrl;
|
|
|
104 } else {
|
|
|
105 document.getElementById('error-msg').style.display = 'block';
|
|
|
106 }
|
|
|
107 } catch (err) {
|
|
|
108 document.getElementById('error-msg').style.display = 'block';
|
|
|
109 }
|
|
|
110 });
|
|
|
111 </script>
|
|
|
112 </body>
|
|
|
113 </html>
|