/** * Servicio de autenticación para Dolibarr * * Maneja login, logout y gestión de tokens/sesiones */ // Tipos para la autenticación export interface AuthUser { id: number; login: string; firstname: string; lastname: string; email: string; admin: boolean; } export interface LoginCredentials { login: string; password: string; } export interface LoginResponse { success: boolean; token?: string; user?: AuthUser; error?: string; } export interface AuthState { isAuthenticated: boolean; user: AuthUser | null; token: string | null; } // Constantes const AUTH_TOKEN_KEY = "dolibarr_auth_token"; const AUTH_USER_KEY = "dolibarr_auth_user"; /** * Obtiene la URL base de la API de Dolibarr */ function getApiUrl(): string { // Intentar obtener del entorno (cliente usa NEXT_PUBLIC_) const url = typeof window !== "undefined" ? process.env.NEXT_PUBLIC_API_URL : process.env.DOLIBARR_API_URL || process.env.NEXT_PUBLIC_API_URL; if (!url) { throw new Error("API URL not configured"); } return url; } /** * Realiza login contra la API de Dolibarr * Dolibarr usa el endpoint /login para autenticar y devuelve un token */ export async function login(credentials: LoginCredentials): Promise { try { const apiUrl = getApiUrl(); // Dolibarr API login endpoint const response = await fetch(`${apiUrl}/login`, { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json", }, body: JSON.stringify({ login: credentials.login, password: credentials.password, }), }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); if (response.status === 401 || response.status === 403) { return { success: false, error: "Credenciales incorrectas. Verifica tu usuario y contraseña.", }; } return { success: false, error: errorData.error || `Error del servidor: ${response.status}`, }; } const data = await response.json(); // Dolibarr devuelve el token directamente en success.token const token = data.success?.token || data.token; if (!token) { return { success: false, error: "No se recibió token de autenticación", }; } // Obtener información del usuario con el token const userResponse = await fetch(`${apiUrl}/users/info?DOLAPIKEY=${token}`, { headers: { "Accept": "application/json", }, }); let user: AuthUser | undefined; if (userResponse.ok) { const userData = await userResponse.json(); user = { id: parseInt(userData.id), login: userData.login, firstname: userData.firstname || "", lastname: userData.lastname || "", email: userData.email || "", admin: userData.admin === "1" || userData.admin === 1, }; } // Guardar en localStorage saveAuthData(token, user); return { success: true, token, user, }; } catch (error) { console.error("Login error:", error); return { success: false, error: "Error de conexión. Verifica tu conexión a internet.", }; } } /** * Realiza logout - limpia datos locales * Nota: Dolibarr no tiene endpoint de logout, los tokens expiran solos */ export async function logout(): Promise { // Limpiar datos de autenticación clearAuthData(); } /** * Guarda los datos de autenticación en localStorage y cookie */ function saveAuthData(token: string, user?: AuthUser): void { if (typeof window === "undefined") return; localStorage.setItem(AUTH_TOKEN_KEY, token); if (user) { localStorage.setItem(AUTH_USER_KEY, JSON.stringify(user)); } // También guardar en cookie para que el middleware pueda leerlo document.cookie = `${AUTH_TOKEN_KEY}=${token}; path=/; max-age=${60 * 60 * 24 * 7}; SameSite=Lax`; } /** * Limpia los datos de autenticación */ function clearAuthData(): void { if (typeof window === "undefined") return; localStorage.removeItem(AUTH_TOKEN_KEY); localStorage.removeItem(AUTH_USER_KEY); // Limpiar cookie document.cookie = `${AUTH_TOKEN_KEY}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`; } /** * Obtiene el token guardado */ export function getStoredToken(): string | null { if (typeof window === "undefined") return null; return localStorage.getItem(AUTH_TOKEN_KEY); } /** * Obtiene el usuario guardado */ export function getStoredUser(): AuthUser | null { if (typeof window === "undefined") return null; const userJson = localStorage.getItem(AUTH_USER_KEY); if (!userJson) return null; try { return JSON.parse(userJson); } catch { return null; } } /** * Verifica si el token actual es válido */ export async function verifyToken(): Promise { const token = getStoredToken(); if (!token) { return false; } try { const apiUrl = getApiUrl(); // Verificar token haciendo una llamada simple a la API const response = await fetch(`${apiUrl}/users/info?DOLAPIKEY=${token}`, { headers: { "Accept": "application/json", }, }); if (!response.ok) { // Token inválido o expirado clearAuthData(); return false; } return true; } catch { return false; } } /** * Obtiene el estado de autenticación actual */ export function getAuthState(): AuthState { const token = getStoredToken(); const user = getStoredUser(); return { isAuthenticated: !!token, user, token, }; }