const LEGACY_AUTH_KEYS = ['token', 'role', 'departmentId', 'userId']; let accessToken = null; let authState = null; let refreshPromise = null; purgeLegacyAuthStorage(); export function getAccessToken() { return accessToken; } export function getAuthState() { return authState ? { ...authState } : null; } export function storeAuthState(data) { if (!data?.token || !data?.role) { clearAuthState(); return null; } accessToken = data.token; authState = { role: data.role, departmentId: normalizeOptionalId(data.departmentId), userId: normalizeOptionalId(data.userId), redirect: typeof data.redirect === 'string' ? data.redirect : '/' }; return getAuthState(); } export function clearAuthState() { accessToken = null; authState = null; } export async function restoreSession() { if (accessToken && authState) { return getAuthState(); } const refreshed = await refreshAccessToken(); return refreshed ? getAuthState() : null; } export async function refreshAccessToken() { if (refreshPromise) { return refreshPromise; } refreshPromise = (async () => { let response; try { response = await fetch('/api/auth/refresh', { method: 'POST', credentials: 'same-origin' }); } catch (error) { clearAuthState(); return false; } const data = await response.json().catch(() => null); if (!response.ok || !storeAuthState(data)) { clearAuthState(); return false; } return true; })().finally(() => { refreshPromise = null; }); return refreshPromise; } export async function fetchWithAuth(endpoint, options = {}, retryOnUnauthorized = true) { const headers = new Headers(options.headers || {}); if (accessToken) { headers.set('Authorization', `Bearer ${accessToken}`); } const response = await fetch(endpoint, { ...options, headers, credentials: 'same-origin' }); if (response.status === 401 && retryOnUnauthorized && await refreshAccessToken()) { return fetchWithAuth(endpoint, options, false); } return response; } export async function logoutSession() { try { await fetch('/api/auth/logout', { method: 'POST', credentials: 'same-origin' }); } catch (error) { console.warn('Не удалось завершить серверную сессию'); } finally { clearAuthState(); } } function purgeLegacyAuthStorage() { try { LEGACY_AUTH_KEYS.forEach(key => localStorage.removeItem(key)); LEGACY_AUTH_KEYS.forEach(key => sessionStorage.removeItem(key)); } catch (error) { console.warn('Не удалось очистить устаревшие данные авторизации в браузере'); } } function normalizeOptionalId(value) { return value === undefined || value === null || value === '' ? null : String(value); }