"use strict"; /** * AuthController - Controlador de Autenticación * * Endpoints REST para login, register, refresh y logout. * Implementa validación de datos y manejo de errores. * * @module Auth */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createAuthController = createAuthController; const express_1 = require("express"); const auth_service_1 = require("../services/auth.service"); const auth_middleware_1 = require("../middleware/auth.middleware"); const user_entity_1 = require("../../core/entities/user.entity"); const tenant_entity_1 = require("../../core/entities/tenant.entity"); const refresh_token_entity_1 = require("../entities/refresh-token.entity"); /** * Crear router de autenticación */ function createAuthController(dataSource) { const router = (0, express_1.Router)(); // Inicializar repositorios const userRepository = dataSource.getRepository(user_entity_1.User); const tenantRepository = dataSource.getRepository(tenant_entity_1.Tenant); const refreshTokenRepository = dataSource.getRepository(refresh_token_entity_1.RefreshToken); // Inicializar servicio const authService = new auth_service_1.AuthService(userRepository, tenantRepository, refreshTokenRepository); // Inicializar middleware const authMiddleware = new auth_middleware_1.AuthMiddleware(authService, dataSource); /** * POST /auth/login * Login de usuario */ router.post('/login', async (req, res, next) => { try { const dto = req.body; if (!dto.email || !dto.password) { res.status(400).json({ error: 'Bad Request', message: 'Email and password are required', }); return; } const result = await authService.login(dto); res.status(200).json({ success: true, data: result }); } catch (error) { if (error instanceof Error) { if (error.message === 'Invalid credentials') { res.status(401).json({ error: 'Unauthorized', message: 'Invalid email or password' }); return; } if (error.message === 'User is not active') { res.status(403).json({ error: 'Forbidden', message: 'User account is disabled' }); return; } if (error.message === 'No tenant specified' || error.message === 'Tenant not found or inactive') { res.status(400).json({ error: 'Bad Request', message: error.message }); return; } } next(error); } }); /** * POST /auth/register * Registro de nuevo usuario */ router.post('/register', async (req, res, next) => { try { const dto = req.body; if (!dto.email || !dto.password || !dto.firstName || !dto.lastName || !dto.tenantId) { res.status(400).json({ error: 'Bad Request', message: 'Email, password, firstName, lastName and tenantId are required', }); return; } const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(dto.email)) { res.status(400).json({ error: 'Bad Request', message: 'Invalid email format' }); return; } if (dto.password.length < 8) { res.status(400).json({ error: 'Bad Request', message: 'Password must be at least 8 characters' }); return; } const result = await authService.register(dto); res.status(201).json({ success: true, data: result }); } catch (error) { if (error instanceof Error) { if (error.message === 'Email already registered') { res.status(409).json({ error: 'Conflict', message: 'Email is already registered' }); return; } if (error.message === 'Tenant not found') { res.status(400).json({ error: 'Bad Request', message: 'Invalid tenant ID' }); return; } } next(error); } }); /** * POST /auth/refresh * Renovar access token usando refresh token */ router.post('/refresh', async (req, res, next) => { try { const dto = req.body; if (!dto.refreshToken) { res.status(400).json({ error: 'Bad Request', message: 'Refresh token is required' }); return; } const result = await authService.refresh(dto); res.status(200).json({ success: true, data: result }); } catch (error) { if (error instanceof Error) { if (error.message === 'Invalid refresh token' || error.message === 'Refresh token expired or revoked') { res.status(401).json({ error: 'Unauthorized', message: error.message }); return; } if (error.message === 'User not found or inactive') { res.status(401).json({ error: 'Unauthorized', message: 'User account is disabled or deleted' }); return; } } next(error); } }); /** * POST /auth/logout * Cerrar sesión (revocar refresh token) */ router.post('/logout', authMiddleware.authenticate, async (req, res, next) => { try { const { refreshToken } = req.body; if (refreshToken) { await authService.logout(refreshToken); } res.status(200).json({ success: true, message: 'Logged out successfully' }); } catch (error) { next(error); } }); /** * POST /auth/change-password * Cambiar contraseña (requiere autenticación) */ router.post('/change-password', authMiddleware.authenticate, async (req, res, next) => { try { const dto = req.body; const userId = req.user?.sub; if (!userId) { res.status(401).json({ error: 'Unauthorized', message: 'User not authenticated' }); return; } if (!dto.currentPassword || !dto.newPassword) { res.status(400).json({ error: 'Bad Request', message: 'Current password and new password are required' }); return; } if (dto.newPassword.length < 8) { res.status(400).json({ error: 'Bad Request', message: 'New password must be at least 8 characters' }); return; } await authService.changePassword(userId, dto); res.status(200).json({ success: true, message: 'Password changed successfully' }); } catch (error) { if (error instanceof Error && error.message === 'Current password is incorrect') { res.status(400).json({ error: 'Bad Request', message: 'Current password is incorrect' }); return; } next(error); } }); /** * GET /auth/me * Obtener información del usuario autenticado */ router.get('/me', authMiddleware.authenticate, async (req, res, next) => { try { const userId = req.user?.sub; if (!userId) { res.status(401).json({ error: 'Unauthorized', message: 'User not authenticated' }); return; } const user = await userRepository.findOne({ where: { id: userId }, select: ['id', 'email', 'firstName', 'lastName', 'isActive', 'createdAt'], }); if (!user) { res.status(404).json({ error: 'Not Found', message: 'User not found' }); return; } res.status(200).json({ success: true, data: { id: user.id, email: user.email, firstName: user.firstName, lastName: user.lastName, roles: req.user?.roles || [], tenantId: req.tenantId, }, }); } catch (error) { next(error); } }); /** * GET /auth/verify * Verificar si el token es válido */ router.get('/verify', authMiddleware.authenticate, (req, res) => { res.status(200).json({ success: true, data: { valid: true, user: { id: req.user?.sub, email: req.user?.email, roles: req.user?.roles, }, tenantId: req.tenantId, }, }); }); return router; } exports.default = createAuthController; //# sourceMappingURL=auth.controller.js.map