photo_server_json_con_aves22/public/js/logout.js
2026-04-18 20:14:42 +02:00

147 lines
3.8 KiB
JavaScript

// ===============================
// LOGOUT — pulizia token + revoca + auto-logout JWT
// ===============================
(() => {
const AUTH_LOGOUT_ENDPOINT = "/auth/logout";
const TOKEN_KEYS = ["token", "access_token", "refresh_token"];
// -------------------------------
// Helpers token
// -------------------------------
function getToken() {
try {
return (
localStorage.getItem("token") ||
localStorage.getItem("access_token") ||
""
);
} catch {
return "";
}
}
function clearTokens() {
try {
TOKEN_KEYS.forEach(k => localStorage.removeItem(k));
} catch {}
}
// -------------------------------
// Logout lato server
// -------------------------------
async function serverLogout(token) {
try {
const headers = token ? { Authorization: `Bearer ${token}` } : {};
await fetch(AUTH_LOGOUT_ENDPOINT, { method: "POST", headers });
} catch (err) {
console.warn("Logout server fallito (ignoro):", err);
}
}
// -------------------------------
// Redirect
// -------------------------------
function getRedirectUrl() {
const btn = document.querySelector("[data-logout]");
return btn?.getAttribute("data-redirect") || "/";
}
function redirect(url) {
window.location.assign(url || "/");
}
// -------------------------------
// Auto-logout alla scadenza JWT
// -------------------------------
let autoLogoutTimer = null;
function scheduleAutoLogout() {
clearTimeout(autoLogoutTimer);
const token = getToken();
if (!token) return;
const payload = parseJwt(token); // usa la funzione globale già esistente
const expSec = payload?.exp;
if (!expSec) return;
const msToExp = expSec * 1000 - Date.now();
if (msToExp <= 0) {
doLogout({ doRedirect: true });
return;
}
autoLogoutTimer = setTimeout(() => {
doLogout({ doRedirect: true });
}, msToExp);
}
// -------------------------------
// UI helpers
// -------------------------------
function setButtonsDisabled(disabled) {
document.querySelectorAll("[data-logout]").forEach(btn => {
btn.disabled = disabled;
btn.setAttribute("aria-busy", disabled ? "true" : "false");
});
}
// -------------------------------
// Azione principale
// -------------------------------
async function doLogout({ doRedirect = true } = {}) {
const token = getToken();
setButtonsDisabled(true);
await serverLogout(token);
clearTokens();
try {
window.dispatchEvent(new CustomEvent("logout:success"));
} catch {}
if (doRedirect) redirect(getRedirectUrl());
setButtonsDisabled(false);
}
// -------------------------------
// Bind pulsanti
// -------------------------------
function bindLogoutButtons() {
document.querySelectorAll("[data-logout]").forEach(btn => {
btn.addEventListener("click", async (e) => {
e.preventDefault();
if (btn.disabled) return;
await doLogout({ doRedirect: true });
});
});
}
// -------------------------------
// Public API
// -------------------------------
window.AppAuth = Object.freeze({
logout: (opts) => doLogout(opts),
isLoggedIn: () => !!getToken()
});
// -------------------------------
// Init
// -------------------------------
function init() {
bindLogoutButtons();
scheduleAutoLogout();
document.querySelectorAll("[data-logout]").forEach(btn => {
if (!window.AppAuth.isLoggedIn()) btn.style.display = "none";
});
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();