// Sistema de Autenticação Frontend class AuthManager { constructor() { this.token = localStorage.getItem('token'); this.usuario = JSON.parse(localStorage.getItem('usuario') || 'null'); this.verificandoAuth = false; // Flag para evitar verificações múltiplas console.log('🔧 AuthManager initialized'); console.log('🎫 Token from localStorage:', this.token ? 'EXISTS' : 'MISSING'); console.log('👤 User from localStorage:', this.usuario ? this.usuario.nome : 'MISSING'); // Configurar interceptor IMEDIATAMENTE this.setupFetchInterceptor(); // NÃO verificar auth aqui para evitar múltiplas chamadas // A verificação será feita apenas uma vez após o DOM carregar } // Verificar se está autenticado isAuthenticated() { return !!this.token; } // Obter token getToken() { return this.token; } // Obter dados do usuário getUsuario() { return this.usuario; } // Verificar autenticação no servidor async verificarAuth() { if (this.verificandoAuth) { return; // Evitar verificações múltiplas } if (!this.token) { this.redirectToLogin(); return false; } this.verificandoAuth = true; try { const response = await fetch('/api/auth/verificar', { headers: { 'Authorization': 'Bearer ' + this.token } }); if (response.ok) { const data = await response.json(); if (data.status === 'success') { this.usuario = data.usuario; localStorage.setItem('usuario', JSON.stringify(this.usuario)); this.atualizarInterface(); this.verificandoAuth = false; return true; } } // Token inválido this.verificandoAuth = false; this.logout(); return false; } catch (error) { console.error('Erro ao verificar autenticação:', error); this.verificandoAuth = false; this.logout(); return false; } } // Fazer logout async logout() { try { if (this.token) { await fetch('/api/auth/logout', { method: 'POST', headers: { 'Authorization': 'Bearer ' + this.token } }); } } catch (error) { console.error('Erro no logout:', error); } // Limpar dados locais localStorage.removeItem('token'); localStorage.removeItem('usuario'); this.token = null; this.usuario = null; this.redirectToLogin(); } // Redirecionar para login redirectToLogin() { if (window.location.pathname !== '/login.html' && window.location.pathname !== '/login') { window.location.href = '/login.html'; } } // Atualizar interface com dados do usuário atualizarInterface() { if (this.usuario) { // Atualizar nome do usuário na navbar const userElements = document.querySelectorAll('.user-name'); userElements.forEach(el => { el.textContent = this.usuario.nome; }); // Adicionar informações do usuário na navbar this.adicionarMenuUsuario(); } } // Adicionar menu do usuário na navbar adicionarMenuUsuario() { const navbar = document.querySelector('.navbar-nav'); if (navbar && !document.querySelector('#userMenu')) { const userMenu = document.createElement('li'); userMenu.className = 'nav-item dropdown'; userMenu.id = 'userMenu'; userMenu.innerHTML = ` ${this.usuario.nome} `; navbar.appendChild(userMenu); } } // Mostrar modal com informações do perfil mostrarPerfil() { const modalHtml = ` `; // Remover modal existente se houver const existingModal = document.getElementById('modalPerfil'); if (existingModal) { existingModal.remove(); } // Adicionar novo modal document.body.insertAdjacentHTML('beforeend', modalHtml); // Mostrar modal const modal = new bootstrap.Modal(document.getElementById('modalPerfil')); modal.show(); } // Interceptar chamadas fetch para adicionar token setupFetchInterceptor() { const originalFetch = window.fetch; const authManager = this; window.fetch = async (url, options = {}) => { // Não interceptar verificações de autenticação para evitar loop if (url.includes('/api/auth/verificar') || url.includes('/verificar')) { return originalFetch(url, options); } console.log('🔍 Fetch intercepted:', url, 'Token:', authManager.token ? 'EXISTS' : 'MISSING'); // Adicionar token nas requisições para a API (exceto rotas de auth) if (url.startsWith('/api/') && authManager.token && !url.includes('/api/auth/')) { options.headers = { ...options.headers, 'Authorization': 'Bearer ' + authManager.token }; console.log('✅ Token added to request:', url); } const response = await originalFetch(url, options); // Log da resposta console.log('📡 Response status:', response.status, 'for URL:', url); // Se receber 401, fazer logout (exceto para rotas de auth) if (response.status === 401 && url.startsWith('/api/') && !url.includes('/api/auth/')) { console.log('❌ 401 received, logging out'); authManager.logout(); } return response; }; } } // Inicializar gerenciador de autenticação const authManager = new AuthManager(); // Verificar autenticação quando a página carrega (apenas uma vez) let authCheckExecuted = false; function executeAuthCheck() { if (authCheckExecuted || authManager.verificandoAuth) { return; } authCheckExecuted = true; authManager.verificarAuth(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', executeAuthCheck); } else { // Documento já carregado executeAuthCheck(); }