const API_URL = ""; // Relative path since served by same origin // State let token = localStorage.getItem("token"); let currentUser = null; // DOM Elements const loginPage = document.getElementById("login-page"); const dashboardLayout = document.getElementById("dashboard-layout"); const loginForm = document.getElementById("login-form"); const loginError = document.getElementById("login-error"); const logoutBtn = document.getElementById("logout-btn"); const usersSection = document.getElementById("users-section"); const appsSection = document.getElementById("apps-section"); const usersTableBody = document.querySelector("#users-table tbody"); const appsTableBody = document.querySelector("#apps-table tbody"); // Init function init() { if (token) { showDashboard(); } else { showLogin(); } } // Navigation function showLogin() { loginPage.classList.remove("hidden"); dashboardLayout.classList.add("hidden"); } function showDashboard() { loginPage.classList.add("hidden"); dashboardLayout.classList.remove("hidden"); loadUsers(); } function showSection(section) { if (section === 'users') { usersSection.classList.remove("hidden"); appsSection.classList.add("hidden"); loadUsers(); } else { usersSection.classList.add("hidden"); appsSection.classList.remove("hidden"); loadApps(); } } // Auth loginForm.addEventListener("submit", async (e) => { e.preventDefault(); const username = document.getElementById("username").value; const password = document.getElementById("password").value; try { const formData = new FormData(); formData.append("username", username); formData.append("password", password); const res = await fetch(`${API_URL}/token`, { method: "POST", body: formData }); if (!res.ok) throw new Error("Invalid credentials"); const data = await res.json(); token = data.access_token; localStorage.setItem("token", token); loginError.classList.add("hidden"); showDashboard(); } catch (err) { loginError.textContent = err.message; loginError.classList.remove("hidden"); } }); logoutBtn.addEventListener("click", () => { token = null; localStorage.removeItem("token"); showLogin(); }); // API Helpers async function authFetch(url, options = {}) { const headers = { ...options.headers, "Authorization": `Bearer ${token}` }; const res = await fetch(url, { ...options, headers }); if (res.status === 401) { logoutBtn.click(); throw new Error("Unauthorized"); } return res; } // Users async function loadUsers() { const res = await authFetch(`${API_URL}/users/`); const users = await res.json(); usersTableBody.innerHTML = users.map(user => { const appsList = user.applications.map(ua => ` ${ua.application.name} ` ).join(""); return ` ${user.id} ${user.username} ${user.email} ${user.is_admin ? "Yes" : "No"} ${user.is_active ? "Yes" : "No"} ${appsList} `}).join(""); } window.removeAppAssignment = async (userId, appId) => { if (!confirm("Are you sure you want to remove this app assignment?")) return; try { const res = await authFetch(`${API_URL}/users/${userId}/assign/${appId}`, { method: "DELETE" }); if (!res.ok) throw new Error("Failed to remove assignment"); loadUsers(); } catch (err) { alert(err.message); } }; // Apps async function loadApps() { const res = await authFetch(`${API_URL}/apps/`); const apps = await res.json(); appsTableBody.innerHTML = apps.map(app => ` ${app.id} ${app.name} ${app.url} ${app.api_key} `).join(""); } // Modals function openModal(id) { document.getElementById(id).classList.remove("hidden"); } function closeModal(id) { document.getElementById(id).classList.add("hidden"); } // User Form const userForm = document.getElementById("user-form"); userForm.addEventListener("submit", async (e) => { e.preventDefault(); const id = document.getElementById("user-id").value; const username = document.getElementById("user-username").value; const email = document.getElementById("user-email").value; const password = document.getElementById("user-password").value; const isAdmin = document.getElementById("user-is-admin").checked; const isActive = document.getElementById("user-is-active").checked; const data = { username, email, is_admin: isAdmin, is_active: isActive }; if (password) data.password = password; try { let res; if (id) { res = await authFetch(`${API_URL}/users/${id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }); } else { if (!password) return alert("Password required for new user"); res = await authFetch(`${API_URL}/users/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }); } if (!res.ok) { const err = await res.json(); throw new Error(err.detail); } closeModal("user-modal"); loadUsers(); } catch (err) { alert(err.message); } }); window.addUser = () => { document.getElementById("user-id").value = ""; document.getElementById("user-username").value = ""; document.getElementById("user-email").value = ""; document.getElementById("user-password").value = ""; document.getElementById("user-is-admin").checked = false; document.getElementById("user-is-active").checked = true; openModal("user-modal"); }; window.addApp = () => { document.getElementById("app-name").value = ""; document.getElementById("app-url").value = ""; openModal("app-modal"); }; window.editUser = (user) => { document.getElementById("user-id").value = user.id; document.getElementById("user-username").value = user.username; document.getElementById("user-email").value = user.email; document.getElementById("user-password").value = ""; document.getElementById("user-is-admin").checked = user.is_admin; document.getElementById("user-is-active").checked = user.is_active; openModal("user-modal"); }; // App Form const appForm = document.getElementById("app-form"); appForm.addEventListener("submit", async (e) => { e.preventDefault(); const name = document.getElementById("app-name").value; const url = document.getElementById("app-url").value; try { const res = await authFetch(`${API_URL}/apps/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name, url }) }); if (!res.ok) { const err = await res.json(); throw new Error(err.detail); } closeModal("app-modal"); loadApps(); } catch (err) { alert(err.message); } }); // Assign App window.assignAppModal = async (userId) => { document.getElementById("assign-user-id").value = userId; // Load apps for select const res = await authFetch(`${API_URL}/apps/`); const apps = await res.json(); const select = document.getElementById("assign-app-select"); select.innerHTML = '' + apps.map(app => ``).join(""); openModal("assign-modal"); }; const assignForm = document.getElementById("assign-form"); assignForm.addEventListener("submit", async (e) => { e.preventDefault(); const userId = document.getElementById("assign-user-id").value; const appId = document.getElementById("assign-app-select").value; try { const res = await authFetch(`${API_URL}/users/${userId}/assign/${appId}`, { method: "POST" }); if (!res.ok) throw new Error("Failed to assign"); closeModal("assign-modal"); alert("Assigned successfully"); } catch (err) { alert(err.message); } }); // Start init();