Files
sso/frontend/static/js/app.js
2026-01-25 14:36:01 +01:00

258 lines
7.6 KiB
JavaScript

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 => `
<tr>
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.email}</td>
<td>${user.is_admin ? "Yes" : "No"}</td>
<td>${user.is_active ? "Yes" : "No"}</td>
<td>
<button class="btn btn-secondary" onclick='editUser(${JSON.stringify(user)})'>Edit</button>
<button class="btn btn-primary" onclick='assignAppModal(${user.id})'>Assign App</button>
</td>
</tr>
`).join("");
}
// Apps
async function loadApps() {
const res = await authFetch(`${API_URL}/apps/`);
const apps = await res.json();
appsTableBody.innerHTML = apps.map(app => `
<tr>
<td>${app.id}</td>
<td>${app.name}</td>
<td>${app.url}</td>
<td><code>${app.api_key}</code></td>
</tr>
`).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.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 = '<option value="">Select Application</option>' +
apps.map(app => `<option value="${app.id}">${app.name}</option>`).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();