user admin

This commit is contained in:
2026-08-27 15:57:48 +02:00
parent 84891adb89
commit ffd077bb4d
15 changed files with 765 additions and 24 deletions
+76 -2
View File
@@ -32,6 +32,13 @@ const elements = {
format: document.querySelector("#audio-format"),
source: document.querySelector("#audio-source"),
status: document.querySelector("#status"),
logout: document.querySelector("#logout"),
loginOverlay: document.querySelector("#login-overlay"),
loginForm: document.querySelector("#login-form"),
loginUsername: document.querySelector("#login-username"),
loginPassword: document.querySelector("#login-password"),
loginError: document.querySelector("#login-error"),
loginSubmit: document.querySelector("#login-submit"),
};
let state = null;
@@ -39,6 +46,14 @@ let seekBusy = false;
let draggedTrack = null;
let commandBusy = false;
class ApiError extends Error {
constructor(message, status, code) {
super(message);
this.status = status;
this.code = code;
}
}
function formatTime(value) {
if (!Number.isFinite(value) || value < 0) return "00:00:00";
const whole = Math.floor(value);
@@ -62,10 +77,34 @@ async function api(path, body) {
};
const response = await fetch(path, options);
const data = await response.json();
if (!response.ok) throw new Error(data.error || `HTTP ${response.status}`);
if (!response.ok) {
throw new ApiError(data.error || `HTTP ${response.status}`, response.status, data.code);
}
return data;
}
function showLogin(message = null) {
if (message !== null) elements.loginError.textContent = message;
elements.loginOverlay.hidden = false;
window.setTimeout(() => elements.loginUsername.focus(), 0);
}
function hideLogin() {
elements.loginOverlay.hidden = true;
elements.loginError.textContent = "";
elements.loginPassword.value = "";
}
async function refreshAuth() {
try {
const auth = await api("/api/auth/status");
elements.logout.hidden = !auth.enabled || auth.local || !auth.authenticated;
if (auth.enabled && !auth.local && !auth.authenticated) showLogin();
} catch (error) {
setStatus(`Authenticatiestatus onbekend: ${error.message}`);
}
}
async function command(name, data = {}, pendingMessage = "") {
if (pendingMessage) setStatus(pendingMessage);
commandBusy = true;
@@ -441,10 +480,45 @@ async function refresh() {
if (commandBusy) return;
try {
render(await api("/api/state"));
hideLogin();
} catch (error) {
setStatus(`Geen verbinding: ${error.message}`);
if (error.code === "authentication-required") {
showLogin();
} else {
setStatus(`Geen verbinding: ${error.message}`);
}
}
}
elements.loginForm.addEventListener("submit", async (event) => {
event.preventDefault();
elements.loginSubmit.disabled = true;
elements.loginError.textContent = "";
try {
await api("/api/auth/login", {
username: elements.loginUsername.value,
password: elements.loginPassword.value,
});
hideLogin();
await refreshAuth();
await refresh();
} catch (error) {
showLogin(error.message);
elements.loginPassword.select();
} finally {
elements.loginSubmit.disabled = false;
}
});
elements.logout.addEventListener("click", async () => {
try {
await api("/api/auth/logout", {});
} finally {
elements.logout.hidden = true;
showLogin("Je bent uitgelogd.");
}
});
refreshAuth();
refresh();
setInterval(refresh, 1000);