// =============================== // 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(); } })();