login.html 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>DezuKVM | Login</title>
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <link rel="icon" type="image/png" href="/favicon.png">
  8. <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  9. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.9.4/semantic.min.css" integrity="sha512-ySrYzxj+EI1e9xj/kRYqeDL5l1wW0IWY8pzHNTIZ+vc1D3Z14UDNPbwup4yOUmlRemYjgUXsUZ/xvCQU2ThEAw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
  10. <script src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.9.4/semantic.min.js" integrity="sha512-Y/wIVu+S+XJsDL7I+nL50kAVFLMqSdvuLqF2vMoRqiMkmvcqFjEpEgeu6Rx8tpZXKp77J8OUpMKy0m3jLYhbbw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  11. <style>
  12. html, body {
  13. height: 100%;
  14. margin: 0;
  15. padding: 0;
  16. font-family: Arial, Helvetica, sans-serif;
  17. }
  18. body {
  19. height: 100vh;
  20. display: flex;
  21. align-items: center;
  22. justify-content: center;
  23. background: #f5f5f5;
  24. color: #222;
  25. }
  26. .login-container {
  27. background: #fff;
  28. padding: 2rem 2.5rem;
  29. border-radius: 8px;
  30. box-shadow: 0 2px 16px rgba(0,0,0,0.08);
  31. min-width: 420px;
  32. display: flex;
  33. flex-direction: column;
  34. align-items: center;
  35. }
  36. @media (prefers-color-scheme: dark) {
  37. body {
  38. background: #181a1b !important;
  39. color: #f1f1f1 !important;
  40. }
  41. .login-container {
  42. background: #23272a;
  43. box-shadow: 0 2px 16px rgba(0,0,0,0.32);
  44. }
  45. .login-container .error-message {
  46. background: #3a2323;
  47. color: #ffb3b3;
  48. border-color: #a94442;
  49. }
  50. input, .ui.input > input {
  51. background: #181a1b !important;
  52. color: #f1f1f1 !important;
  53. border-color: #444 !important;
  54. }
  55. .ui.basic.button {
  56. background: #23272a !important;
  57. color: #f1f1f1 !important;
  58. border-color: #444 !important;
  59. }
  60. .ui.basic.button:hover,
  61. .ui.basic.button:focus {
  62. background: #181a1b !important;
  63. color: #fff !important;
  64. border-color: #666 !important;
  65. }
  66. }
  67. .login-container form {
  68. width: 100%;
  69. display: flex;
  70. flex-direction: column;
  71. gap: 1rem;
  72. }
  73. .login-container .error-message {
  74. margin-top: 1rem;
  75. color: #d32f2f;
  76. background: #ffeaea;
  77. border: 1px solid #f5c6cb;
  78. border-radius: 4px;
  79. padding: 0.5rem;
  80. width: 100%;
  81. text-align: center;
  82. display: none;
  83. }
  84. </style>
  85. </head>
  86. <body>
  87. <div class="login-container ui basic segment">
  88. <img src="img/font_logo.svg" alt="dezuKVM Logo" style="width: 150px; margin-bottom: 1rem;">
  89. <p>Enter your password to access your IP-KVM</p>
  90. <form id="loginForm" autocomplete="off">
  91. <div class="ui action input" style="width:100%;">
  92. <input type="password" id="password" name="password" placeholder="Password" required autofocus>
  93. <button type="button" class="ui basic icon button" id="togglePassword" tabindex="-1">
  94. <i class="ui eye icon" id="eyeIcon"></i>
  95. </button>
  96. </div>
  97. <button class="ui basic button" type="submit"><i class="ui green sign in alternate icon"></i> Login</button>
  98. </form>
  99. <div style="width:100%; margin-top: 1rem; display: flex; justify-content: space-between; font-size: 0.95em;">
  100. <div>
  101. <div class="ui breadcrumb">
  102. <a href="/forgot-password.html" class="section">Forgot Password?</a>
  103. <div class="divider"> / </div>
  104. <a href="https://dezukvm.com" target="_blank" rel="noopener" class="section">DezuKVM</a>
  105. </div>
  106. </div>
  107. </div>
  108. <div class="error-message" id="errorMsg"></div>
  109. </div>
  110. <script>
  111. // $cjax wrapper example (assumes similar to $.ajax)
  112. function $cjax(options) {
  113. var csrfToken = $('meta[name="csrf_token"]').attr('content');
  114. if (!options.headers) options.headers = {};
  115. options.headers['X-CSRF-Token'] = csrfToken;
  116. return $.ajax(options);
  117. }
  118. $(function() {
  119. $('#loginForm').on('submit', function(e) {
  120. e.preventDefault();
  121. $('#errorMsg').hide();
  122. var password = $('#password').val();
  123. $cjax({
  124. url: '/api/v1/login',
  125. method: 'POST',
  126. contentType: 'application/json',
  127. data: JSON.stringify({ password: password }),
  128. success: function(resp, status, xhr) {
  129. if (xhr.status === 200 && !(resp && resp.error)) {
  130. window.location.href = 'index.html';
  131. } else {
  132. var msg = resp && resp.error ? resp.error : 'Login failed.';
  133. $('#errorMsg').text(msg).show();
  134. }
  135. },
  136. error: function(xhr) {
  137. var msg = 'Login failed.';
  138. if (xhr.responseJSON && xhr.responseJSON.error) {
  139. msg = xhr.responseJSON.error;
  140. }
  141. $('#errorMsg').text(msg).show();
  142. }
  143. });
  144. });
  145. });
  146. $('#togglePassword').on('click', function() {
  147. var input = $('#password');
  148. var icon = $('#eyeIcon');
  149. if (input.attr('type') === 'password') {
  150. input.attr('type', 'text');
  151. icon.removeClass('eye').addClass('eye slash');
  152. } else {
  153. input.attr('type', 'password');
  154. icon.removeClass('eye slash').addClass('eye');
  155. }
  156. });
  157. </script>
  158. </body>
  159. </html>