galleria_photo_face_rknn_op.../public/js/auth.js
2026-10-03 12:16:58 +02:00

225 lines
4.5 KiB
JavaScript

// ===============================
// AUTH.JS
// Login, JWT, redirect e auto logout
// ===============================
// Deve rimanere globale se viene usata da altri file
function parseJwt(token) {
try {
const payload = token.split(".")[1];
if (!payload) return null;
const base64 = payload
.replace(/-/g, "+")
.replace(/_/g, "/")
.padEnd(Math.ceil(payload.length / 4) * 4, "=");
const json = decodeURIComponent(
atob(base64)
.split("")
.map((char) =>
`%${char.charCodeAt(0).toString(16).padStart(2, "0")}`
)
.join("")
);
return JSON.parse(json);
} catch (error) {
console.error("[AUTH] JWT non valido:", error);
return null;
}
}
(() => {
"use strict";
const LOGIN_ENDPOINT = "/auth/login";
const LOGIN_PAGE = "/login";
const TOKEN_KEY = "token";
let autoLogoutTimer = null;
// -------------------------------
// TOKEN
// -------------------------------
function saveToken(token) {
try {
localStorage.setItem(TOKEN_KEY, token);
} catch (error) {
console.error("[AUTH] Errore salvataggio token:", error);
}
}
function getToken() {
try {
return localStorage.getItem(TOKEN_KEY) || "";
} catch {
return "";
}
}
function clearToken() {
clearTimeout(autoLogoutTimer);
autoLogoutTimer = null;
try {
localStorage.removeItem(TOKEN_KEY);
} catch (error) {
console.error("[AUTH] Errore rimozione token:", error);
}
}
// -------------------------------
// LOGIN
// -------------------------------
async function login(email, password) {
const response = await fetch(LOGIN_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
const message = await response.text();
throw new Error(message || "Credenziali non valide");
}
const data = await response.json();
if (!data?.token) {
throw new Error("Token mancante nella risposta");
}
saveToken(data.token);
scheduleAutoLogout();
window.dispatchEvent(
new CustomEvent("login:success", {
detail: data,
})
);
return data;
}
// -------------------------------
// VERIFICA AUTENTICAZIONE
// -------------------------------
function isLoggedIn() {
const token = getToken();
const payload = token ? parseJwt(token) : null;
if (!payload?.exp) {
return false;
}
const valid = payload.exp * 1000 > Date.now();
console.log("[AUTH CHECK]", {
valid,
user: payload.name,
exp: new Date(payload.exp * 1000).toISOString(),
});
return valid;
}
function getUser() {
const token = getToken();
return token ? parseJwt(token) : null;
}
function requireAuth(redirectUrl = LOGIN_PAGE) {
if (isLoggedIn()) {
return true;
}
clearToken();
const currentPath =
window.location.pathname +
window.location.search +
window.location.hash;
const separator = redirectUrl.includes("?") ? "&" : "?";
window.location.replace(
`${redirectUrl}${separator}redirect=${encodeURIComponent(currentPath)}`
);
return false;
}
// -------------------------------
// AUTO LOGOUT
// -------------------------------
function scheduleAutoLogout() {
clearTimeout(autoLogoutTimer);
autoLogoutTimer = null;
const payload = getUser();
const expiresAt = payload?.exp ? payload.exp * 1000 : 0;
const timeout = expiresAt - Date.now();
if (!expiresAt) {
return;
}
if (timeout <= 0) {
logout({ redirect: true });
return;
}
autoLogoutTimer = setTimeout(() => {
logout({ redirect: true });
}, timeout);
}
function logout(options = {}) {
clearToken();
if (window.AppAuthLogout?.logout) {
return window.AppAuthLogout.logout(options);
}
if (options.redirect !== false) {
window.location.replace(LOGIN_PAGE);
}
}
// -------------------------------
// INIT
// -------------------------------
function init() {
if (isLoggedIn()) {
scheduleAutoLogout();
}
}
// -------------------------------
// API GLOBALE
// -------------------------------
window.AppAuth = Object.freeze({
login,
logout,
isLoggedIn,
getUser,
requireAuth,
scheduleAutoLogout,
});
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init, { once: true });
} else {
init();
}
})();