Tecnologías Utilizadas
Spring Boot
Spring Boot simplifica el desarrollo mediante la configuración automática de componentes y la integración de servidores embebidos como Tomcat. Su enfoque de convención sobre configuración permite una puesta en marcha rápida con dependencias gestionadas automáticamente, incluyendo módulos como Spring Data y Spring Security para operaciones robustas y seguras.
Vue.js
Vue.js emplea un DOM virtual para optimizar actualizaciones de interfaz mediante enlace de datos reactivo. Este enfoque permite actualizaciones automáticas de UI ante cambios de datos, facilitando la construcción de componentes modulares y mantenibles con un rendimiento eficiente.
MyBatis-Plus
Como extensión de MyBatis, ofrece capacidades ORM mejoradas con soporte multibase de datos. Incluye generación automática de código para entidades y repositorios, además de funciones avanzadas como paginación, bloqueo optimista y consultas dinámicas para acelerar el desarrollo.
Pruebas del Sistema
Objetivos de las Pruebas
Las pruebas garantizan la calidad mediante la identificación temprana de defectos. Se validan los requisitos funcionales y la experiencia de usuario mediante escenarios realistas, priorizando casos de uso relevantes para el dominio de gestión de restaurantes.
Pruebas Funcionales
Se realizaron pruebas de caja negra para validar flujos críticos:
Autenticación
| Datos de Entrada | Resultado Esperado |
|---|---|
| Credenciales válidas | Acceso concedido |
| Contraseña incorrecta | Error de autenticación |
| Usuario vacío | Validación fallida |
Gestión de Usuarios
| Acción | Comportamiento |
|---|---|
| Registro incompleto | Bloqueo por campos obligatorios |
| Edición de perfiles | Actualización persistente |
| Eliminación | Confirmación y borrado |
Conclusión de Pruebas
Los casos de prueba cubrieron todos los escenarios operativos, verificando la estabilidad del sistema y el cumplimiento de los requisitos de negocio para la gestión de restaurantes especializados.
Fragmentos de Código
Controlador de Acceso
@IgnoreAuth
@PostMapping("/autenticar")
public Resultado autenticar(String usuario, String clave, HttpServletRequest solicitud) {
Usuario user = servicioUsuario.buscarPorNombre(usuario);
if (user == null || !user.getClave().equals(clave)) {
return Resultado.error("Credenciales inválidas");
}
String token = servicioToken.crearToken(user.getId(), usuario, "usuarios", user.getRol());
return Resultado.ok().agregar("token", token);
}
Generación de Tokens
public String crearToken(Long idUsuario, String nombre, String tabla, String rol) {
Token tokenExistente = buscarExistente(idUsuario, rol);
String nuevoToken = GeneradorCadena.aleatoria(32);
Date expiracion = new Date(System.currentTimeMillis() + 3600000);
if (tokenExistente != null) {
tokenExistente.setToken(nuevoToken);
tokenExistente.setExpiracion(expiracion);
actualizar(tokenExistente);
} else {
insertar(new Token(idUsuario, nombre, tabla, rol, nuevoToken, expiracion));
}
return nuevoToken;
}
Intercepto de Autorización
@Component
public class InterceptoAutenticacion implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest solicitud, HttpServletResponse respuesta, Object manejador) {
respuesta.setHeader("Access-Control-Allow-Origin", "*");
// Validación de anotación IgnoreAuth
if (manejador instanceof HandlerMethod) {
IgnoreAuth anotacion = ((HandlerMethod) manejador).getMethodAnnotation(IgnoreAuth.class);
if (anotacion != null) return true;
}
String token = solicitud.getHeader("Token-Autorizacion");
if (StringUtils.isBlank(token)) {
enviarError(respuesta, "Autenticación requerida");
return false;
}
// Verificación y almacenamiento en sesión
return true;
}
}
Esquema de Base de Datos
Estructura de Tokens
CREATE TABLE tokens_acceso (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
usuario_id BIGINT NOT NULL,
nombre_usuario VARCHAR(100) NOT NULL,
tabla_asociada VARCHAR(100),
rol VARCHAR(100),
token VARCHAR(200) NOT NULL,
creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expiracion TIMESTAMP
);
INSERT INTO tokens_acceso (usuario_id, nombre_usuario, tabla_asociada, rol, token, expiracion)
VALUES
(23, 'cd01', 'clientes', 'Cliente', 'a1b2c3d4e5', CURRENT_TIMESTAMP + INTERVAL 1 HOUR),
(11, 'xh01', 'empleados', 'Mesero', 'f6g7h8i9j0', CURRENT_TIMESTAMP + INTERVAL 1 HOUR);