Skip to content

test: agregar ReporteServiceTest — 10 tests cubriendo métricas, filtros,...

juan.viera.c requested to merge feat/mailSender-PasswordLogics into master

Descripción del MR ¿Qué problema resolvía este cambio? El sistema no tenía un flujo definido para la gestión de contraseñas. Los usuarios se creaban sin recibir notificación, no había mecanismo para recuperar acceso ante olvido de contraseña, y no existía protección contra ataques de fuerza bruta.

¿Qué se agregó? DataSeeder.java — clase nueva en config/. Contiene la lógica de seed de usuarios iniciales que antes vivía incorrectamente en CustomUsuarioDetailsService. Anotada con @Profile("!test") para no ejecutarse en el entorno de test. EmailService.java — servicio dedicado al envío de emails via Brevo (SMTP). Expone dos métodos: enviarContraseniaTemporal para altas y enviarContraseniaRestablecida para resets. Toda la lógica de transporte está encapsulada acá. PasswordGeneratorService.java — genera contraseñas aleatorias de 10 caracteres garantizando al menos una mayúscula, un número y un símbolo. Usa SecureRandom con Fisher-Yates shuffle para distribución uniforme. AuthService.java — centraliza la lógica de autenticación que antes vivía directamente en AuthController. Incluye el flujo de login con verificación de bloqueo, registro de intentos en log_intentos, lockout automático al 5to intento fallido en 10 minutos, y el flujo de olvido de contraseña. LogIntento.java — entidad que mapea la tabla log_intentos ya existente en el schema. LogIntentoRepository.java — repositorio con query para contar intentos fallidos en una ventana de tiempo. OlvideContraseniaDTO.java — DTO para el endpoint anónimo de recuperación de contraseña. Campo bloqueado BOOLEAN NOT NULL DEFAULT FALSE agregado en proyecto.usuarios (schema y entidad Usuario). Endpoints nuevos en FuncionarioController y EstudianteController: PATCH /{id}/contrasenia y PATCH /{id}/reset-contrasenia. Endpoint nuevo en AuthController: POST /api/auth/olvide-contrasenia. Variables de mail agregadas en application.properties como placeholders ${MAIL_HOST}, ${MAIL_USERNAME}, etc. Las credenciales reales van en variables de entorno, no en el repositorio.

¿Qué se modificó? CustomUsuarioDetailsService — eliminados initUsuarios(), crearSiNoExiste(), y las dependencias de RolRepository y PasswordEncoder. La clase quedó con una única responsabilidad: construir el UserDetails a partir de un ID de usuario. AuthController — eliminada toda la lógica de negocio (queries a repositorios, generación de token, resolución de usuario). Ahora solo delega a AuthService. FuncionarioService.crear — ya no recibe contraseña del DTO. El sistema la genera y envía por email. Estado inicial PENDIENTE_DE_ACTIVACION por default. EstudianteService.crear — mismo cambio que funcionario. FuncionarioService y EstudianteService — agregados cambiarContrasenia y resetContrasenia. El cambio de contraseña desbloquea al usuario y activa si estaba PENDIENTE_DE_ACTIVACION. SienepApplicationTests — simplificado a @SpringBootTest + @ActiveProfiles("test"). application-test.properties — agregadas variables de mail con valores dummy para que el contexto de test levante sin credenciales reales.

¿Qué se eliminó? Campo contrasenia del EstudianteRequestDTO y del FuncionarioRequestDTO — el sistema ya no acepta contraseñas del cliente en el alta.

¿Por qué es mejor así? La contraseña nunca la define el operador que crea el usuario — siempre la genera el sistema y llega directamente al email del titular. Esto elimina el riesgo de que un administrador conozca la contraseña de otro usuario. El lockout por intentos fallidos protege contra fuerza bruta sin necesitar dependencias externas — usa la tabla log_intentos que ya existía en el schema. El AuthService nuevo resuelve el problema señalado por el profesor sobre lógica de negocio en el controlador.

Merge request reports

Loading