Spaces:
Paused
Paused
| <html> | |
| <head> | |
| <title>LibreChat Admin</title> | |
| <style> | |
| body { font-family: Arial, sans-serif; margin: 0; padding: 20px; } | |
| .container { max-width: 1000px; margin: 0 auto; } | |
| table { width: 100%; border-collapse: collapse; margin-top: 20px; } | |
| th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; } | |
| button { padding: 6px 12px; cursor: pointer; } | |
| .login-form { max-width: 400px; margin: 50px auto; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="login" class="login-form" style="display: block;"> | |
| <h2>Admin Login</h2> | |
| <input type="password" id="password" placeholder="Admin Password"> | |
| <button onclick="login()">Login</button> | |
| </div> | |
| <div id="admin-panel" class="container" style="display: none;"> | |
| <h1>User Management</h1> | |
| <div> | |
| <input type="text" id="new-username" placeholder="Username"> | |
| <input type="password" id="new-password" placeholder="Password"> | |
| <button onclick="addUser()">Add User</button> | |
| </div> | |
| <table id="users-table"> | |
| <thead> | |
| <tr> | |
| <th>Username</th> | |
| <th>Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody></tbody> | |
| </table> | |
| </div> | |
| <script> | |
| let authToken = ''; | |
| async function login() { | |
| const password = document.getElementById('password').value; | |
| const response = await fetch('/sudo/login', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ password }) | |
| }); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| authToken = data.token; | |
| document.getElementById('login').style.display = 'none'; | |
| document.getElementById('admin-panel').style.display = 'block'; | |
| loadUsers(); | |
| } else { | |
| alert('Login failed!'); | |
| } | |
| } | |
| async function loadUsers() { | |
| const response = await fetch('/sudo/users', { | |
| headers: { 'X-Auth-Token': authToken } | |
| }); | |
| const users = await response.json(); | |
| const tbody = document.querySelector('#users-table tbody'); | |
| tbody.innerHTML = users.map(user => ` | |
| <tr> | |
| <td>${user.username}</td> | |
| <td> | |
| <button onclick="deleteUser('${user.username}')">Delete</button> | |
| </td> | |
| </tr> | |
| `).join(''); | |
| } | |
| async function addUser() { | |
| const username = document.getElementById('new-username').value; | |
| const password = document.getElementById('new-password').value; | |
| const response = await fetch('/sudo/users', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'X-Auth-Token': authToken | |
| }, | |
| body: JSON.stringify({ username, password }) | |
| }); | |
| if (response.ok) { | |
| loadUsers(); | |
| document.getElementById('new-username').value = ''; | |
| document.getElementById('new-password').value = ''; | |
| } | |
| } | |
| async function deleteUser(username) { | |
| if (confirm(`Delete ${username}?`)) { | |
| await fetch(`/sudo/users/${username}`, { | |
| method: 'DELETE', | |
| headers: { 'X-Auth-Token': authToken } | |
| }); | |
| loadUsers(); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |