import api from '../../../services/api'; import type { User, LoginCredentials, Role } from '../composables/useAuth'; export interface LoginResponse { status: string; data: { user: User; userRoles: Role[]; token: string; }; } export interface RegisterData { name: string; email: string; password: string; password_confirmation: string; } interface SessionRefreshData { user: User; roles: Role[]; permissions: string[]; } class AuthService { private extractArrayFromResponse(payload: unknown): unknown[] { if (Array.isArray(payload)) { return payload; } if (!payload || typeof payload !== 'object') { return []; } const root = payload as Record; if (Array.isArray(root.data)) { return root.data; } if (root.data && typeof root.data === 'object') { const nested = root.data as Record; if (Array.isArray(nested.permissions)) { return nested.permissions; } if (Array.isArray(nested.roles)) { return nested.roles; } } return []; } private normalizePermissions(payload: unknown): string[] { const items = this.extractArrayFromResponse(payload); return items .map((item) => { if (typeof item === 'string') { return item; } if (item && typeof item === 'object' && typeof (item as Record).name === 'string') { return (item as Record).name; } return null; }) .filter((permission): permission is string => Boolean(permission)); } private normalizeRoles(payload: unknown): Role[] { const items = this.extractArrayFromResponse(payload); return items.filter((item): item is Role => { if (!item || typeof item !== 'object') { return false; } const role = item as Partial; return typeof role.name === 'string'; }); } private resolveAuthError(error: any, fallback = 'Error en autenticación'): never { if (error.response?.status === 422 && error.response?.data?.errors) { const firstError = Object.values(error.response.data.errors)?.[0] as string[] | undefined; throw new Error(firstError?.[0] || error.response.data.message || fallback); } if (error.response?.status === 429) { throw new Error('Demasiados intentos de inicio de sesión. Intenta nuevamente en un minuto.'); } throw new Error(error.response?.data?.message || fallback); } /** * Iniciar sesión */ async login(credentials: LoginCredentials): Promise<{ user: User; token: string }> { try { const response = await api.post('/api/auth/login', { email: credentials.email, password: credentials.password }); // Retornar solo user y token para mantener compatibilidad con useAuth return { user: response.data.data.user, token: response.data.data.token }; } catch (error: any) { this.resolveAuthError(error, 'Error al iniciar sesión'); } } /** * Registrar nuevo usuario */ async register(data: RegisterData): Promise { try { const response = await api.post('/api/auth/register', data); return response.data; } catch (error: any) { this.resolveAuthError(error, 'Error al registrar usuario'); } } /** * Cerrar sesión */ async logout(): Promise { try { await api.post('/api/auth/logout'); } catch (error: any) { console.error('Error al cerrar sesión:', error); // No lanzar error para que el logout local continúe aunque falle el backend } } /** * Obtener usuario actual */ async getCurrentUser(): Promise { try { const response = await api.get('/api/user'); return response.data; } catch (error: any) { this.resolveAuthError(error, 'Error al obtener usuario'); } } async getUserRoles(): Promise { try { const response = await api.get('/api/user/roles'); return this.normalizeRoles(response.data); } catch (error: any) { this.resolveAuthError(error, 'Error al obtener roles del usuario'); } } async getUserPermissions(): Promise { try { const response = await api.get('/api/user/permissions'); console.log('User permissions response:', response); return this.normalizePermissions(response.data); } catch (error: any) { this.resolveAuthError(error, 'Error al obtener permisos del usuario'); } } async refreshSession(): Promise { try { const [currentUser, roles, permissions] = await Promise.all([ this.getCurrentUser(), this.getUserRoles(), this.getUserPermissions(), ]); return { user: currentUser, roles, permissions, }; } catch (error: any) { this.resolveAuthError(error, 'Error al sincronizar sesión'); } } /** * Actualizar perfil de usuario */ async updateProfile(data: Partial): Promise { try { const response = await api.put('/api/auth/profile', data); return response.data; } catch (error: any) { this.resolveAuthError(error, 'Error al actualizar perfil'); } } /** * Cambiar contraseña */ async changePassword(currentPassword: string, newPassword: string): Promise { try { await api.post('/api/auth/change-password', { current_password: currentPassword, new_password: newPassword }); } catch (error: any) { this.resolveAuthError(error, 'Error al cambiar contraseña'); } } /** * Solicitar recuperación de contraseña */ async forgotPassword(email: string): Promise { try { await api.post('/api/auth/forgot-password', { email }); } catch (error: any) { this.resolveAuthError(error, 'Error al solicitar recuperación'); } } /** * Resetear contraseña con token */ async resetPassword(token: string, password: string): Promise { try { await api.post('/api/auth/reset-password', { token, password }); } catch (error: any) { this.resolveAuthError(error, 'Error al resetear contraseña'); } } } export const authService = new AuthService(); export default authService;