|
|
||
|---|---|---|
| node_modules | ||
| src | ||
| .env | ||
| README.md | ||
| package-lock.json | ||
| package.json | ||
| server.js | ||
| test-jwt.js | ||
README.md
Backend MVP - API de Gestión de Actividades
Este es un proyecto backend desarrollado con Node.js y Express para gestionar actividades de usuarios con sistema de gamificación (insignias, metas, niveles).
Tabla de Contenidos
- Tecnologías Utilizadas
- Estructura del Proyecto
- Configuración Inicial
- Arquitectura y Flujo de Datos
- Endpoints Disponibles
- Explicación del Código
Tecnologías Utilizadas
- Node.js: Entorno de ejecución de JavaScript
- Express: Framework web para crear la API REST
- MySQL: Base de datos relacional
- JWT (JSON Web Tokens): Autenticación basada en tokens
- bcryptjs: Encriptación de contraseñas
- express-validator: Validación de datos de entrada
- dotenv: Gestión de variables de entorno
- cors: Permitir peticiones desde el frontend
- morgan: Logger de peticiones HTTP
Estructura del Proyecto
backend-mvp/
│
├── server.js # Punto de entrada principal
│
├── src/
│ ├── config/
│ │ └── db.js # Configuración del pool de MySQL
│ │
│ ├── middleware/
│ │ ├── auth.js # Middleware de autenticación (legacy)
│ │ ├── requireAdmin.js # Middleware para verificar rol admin
│ │ └── handleValidation.js # Middleware para procesar validaciones
│ │
│ ├── utils/
│ │ └── jwt.js # Utilidades JWT (sign, verify, requireAuth)
│ │
│ ├── validators/
│ │ ├── auth.validators.js # Validaciones para autenticación
│ │ ├── actividades.validators.js
│ │ ├── categorias.validators.js
│ │ └── ... (otros validadores)
│ │
│ └── routes/
│ ├── auth.routes.js # Rutas de autenticación (login, register)
│ ├── actividades.routes.js
│ ├── categorias.routes.js
│ ├── roles.routes.js
│ ├── insignias.routes.js
│ ├── metas.routes.js
│ ├── niveles.routes.js
│ ├── notificaciones.routes.js
│ ├── agenda.routes.js
│ ├── registroActividad.routes.js
│ ├── usuarioMetricas.routes.js
│ ├── usuarioInsignias.routes.js
│ ├── usuarioRoles.routes.js
│ └── adminMetrics.routes.js
│
├── .env # Variables de entorno (NO incluir en git)
├── package.json # Dependencias del proyecto
└── README.md # Este archivo
Configuración Inicial
1. Instalar dependencias
npm install
2. Configurar variables de entorno
Crear un archivo .env en la raíz del proyecto con el siguiente contenido:
# Base de datos
DB_HOST=localhost
DB_USER=tu_usuario
DB_PASS=tu_contraseña
DB_NAME=nombre_base_datos
DB_PORT=3306
# JWT
JWT_SECRET=tu_secreto_super_seguro_cambiar_en_produccion
# Servidor
PORT=3000
3. Configurar la base de datos
Asegúrate de tener MySQL instalado y crea las tablas necesarias. El proyecto espera las siguientes tablas:
usuarios: Información de usuarios (id_usuario, nombre, apellido, email, password_hash, genero, fecha_registro, activo)roles: Roles del sistema (id_rol, nombre, descripcion)usuarios_roles: Relación muchos a muchos entre usuarios y rolescategorias: Categorías de actividadesactividades: Actividades del sistemainsignias: Insignias/badges del sistema de gamificaciónmetas: Metas/objetivos de usuariosniveles: Niveles del sistema de progresonotificaciones: Sistema de notificacionesagenda: Calendario/planificación de actividadesregistro_actividad: Registro de actividades completadasusuario_metricas: Estadísticas de usuariosusuario_insignias: Insignias obtenidas por usuarios
4. Iniciar el servidor
node server.js
El servidor estará disponible en http://localhost:3000 (o el puerto configurado en .env).
Arquitectura y Flujo de Datos
Flujo General de una Petición
1. Cliente (Frontend) → HTTP Request
↓
2. CORS Middleware (permite peticiones del frontend)
↓
3. Body Parser (convierte JSON a objeto JavaScript)
↓
4. Morgan Logger (registra la petición en consola)
↓
5. Router (encuentra la ruta correspondiente)
↓
6. Validadores (express-validator verifica datos)
↓
7. handleValidation (procesa errores de validación)
↓
8. Middlewares de Autenticación (requireAuth / requireAdmin)
↓
9. Lógica de la Ruta (consultas a BD, procesamiento)
↓
10. Response (JSON con resultado o error)
↓
11. Cliente recibe la respuesta
Flujo de Autenticación
REGISTRO:
Usuario → POST /api/auth/register → Validación → Hash password
→ Insertar en BD → Generar JWT → Devolver token + user
LOGIN:
Usuario → POST /api/auth/login → Validación → Buscar en BD
→ Verificar password → Generar JWT → Devolver token + user
RUTAS PROTEGIDAS:
Usuario → Petición con header "Authorization: Bearer <token>"
→ requireAuth middleware → Verificar token → Adjuntar req.user
→ Continuar a la ruta → Devolver respuesta
Flujo de Validación
Cliente envía datos → Validador (express-validator marca errores)
→ handleValidation middleware
→ Si hay errores: devuelve 400 con lista de errores
→ Si no hay errores: continúa a la lógica de la ruta
Endpoints Disponibles
Autenticación (/api/auth)
| Método | Endpoint | Descripción | Auth | Body |
|---|---|---|---|---|
| POST | /api/auth/register |
Registrar nuevo usuario | No | { nombre, apellido, email, genero, password } |
| POST | /api/auth/login |
Iniciar sesión | No | { email, password } |
| GET | /api/auth/me |
Obtener perfil + roles | Sí | - |
| PUT | /api/auth/me/profile |
Actualizar perfil | Sí | { nombre?, apellido? } |
| PUT | /api/auth/me/password |
Cambiar contraseña | Sí | { actual, nueva } |
Catálogos
| Endpoint | Descripción |
|---|---|
/api/categorias |
CRUD de categorías de actividades |
/api/roles |
CRUD de roles del sistema |
/api/actividades |
CRUD de actividades |
/api/insignias |
CRUD de insignias/badges |
/api/metas |
CRUD de metas/objetivos |
/api/niveles |
CRUD de niveles |
Gestión de Usuario
| Endpoint | Descripción |
|---|---|
/api/notificaciones |
Notificaciones del usuario |
/api/agenda |
Agenda/calendario de actividades |
/api/registroactividad |
Registro de actividades completadas |
/api/metricas |
Métricas y estadísticas del usuario |
/api/usuario-insignias |
Insignias obtenidas por el usuario |
/api/usuario-roles |
Roles asignados al usuario |
Administración
| Endpoint | Descripción |
|---|---|
/api/admin/metrics |
Métricas administrativas del sistema |
Rutas de Prueba
| Método | Endpoint | Descripción |
|---|---|---|
| GET | /public |
Ruta pública de prueba |
| GET | /__ping |
Health check sin autenticación |
| GET | /api/admin/_ping_noauth |
Ping admin sin auth |
| GET | /api/admin/_ping_token |
Ping con autenticación |
Explicación del Código
1. Punto de Entrada (server.js)
Este es el archivo principal que:
- Carga las variables de entorno con
dotenv - Configura Express y los middlewares globales (CORS, body parser, logger)
- Registra todas las rutas de la aplicación
- Inicia el servidor en el puerto especificado
Ver: server.js para documentación detallada línea por línea.
2. Configuración de Base de Datos (src/config/db.js)
Crea un pool de conexiones a MySQL usando mysql2/promise. Un pool reutiliza conexiones en lugar de crear una nueva cada vez, mejorando el rendimiento.
Configuración clave:
connectionLimit: 10→ Máximo 10 conexiones simultáneasnamedPlaceholders: true→ Permite usar:nombreen queries- Lee las credenciales desde variables de entorno (
.env)
Exporta: El pool que se importa en todas las rutas.
Ver: src/config/db.js para más detalles.
3. Utilidades JWT (src/utils/jwt.js)
Maneja todo lo relacionado con JSON Web Tokens:
Funciones principales:
-
signToken(payload, expiresIn)- Genera un token JWT firmado
- Usado en register/login para crear tokens
- Incluye datos del usuario (id_usuario, email)
-
verifyTokenPayload(token)- Verifica que un token sea válido
- Extrae y devuelve el payload decodificado
-
requireAuth(req, res, next)(Middleware)- Protege rutas que requieren autenticación
- Extrae el token del header
Authorization: Bearer <token> - Verifica el token y adjunta
req.usercon los datos del usuario - Si el token es inválido o expiró, devuelve error 401
Flujo de uso:
// En una ruta protegida:
router.get('/perfil', requireAuth, (req, res) => {
console.log(req.user); // { id_usuario: 123, email: 'user@mail.com' }
// ... lógica de la ruta
});
Ver: src/utils/jwt.js para documentación completa.
4. Middlewares
a) handleValidation (src/middleware/handleValidation.js)
Procesa los resultados de express-validator:
- Recoge los errores marcados por los validadores
- Si hay errores: devuelve
400 Bad Requestcon la lista - Si no hay errores: continúa a la ruta
Uso:
router.post('/register', registerValidator, handleValidation, async (req, res) => {
// Si llega aquí, los datos ya fueron validados
});
b) requireAdmin (src/middleware/requireAdmin.js)
Verifica que el usuario autenticado sea administrador:
- Verifica que
req.userexista (debe usarse DESPUÉS derequireAuth) - Consulta la BD para verificar si el usuario tiene rol 'admin'
- Si es admin: continúa; si no: devuelve
403 Forbidden
Uso:
router.get('/admin/users', requireAuth, requireAdmin(), async (req, res) => {
// Solo admins pueden llegar aquí
});
Ver: src/middleware/ para más detalles.
5. Validadores (src/validators/)
Definen reglas de validación usando express-validator.
Ejemplo: auth.validators.js
const registerValidator = [
body('nombre').trim().notEmpty().withMessage('Nombre requerido'),
body('email').isEmail().withMessage('Email inválido'),
body('password').isLength({ min: 6 }).withMessage('Mínimo 6 caracteres'),
];
Flujo:
- Se aplica como middleware en la ruta
express-validatorverifica cada campohandleValidationrecoge los errores y responde
Ver: src/validators/auth.validators.js para ejemplo completo.
6. Rutas (src/routes/)
Cada archivo de rutas maneja un recurso específico (usuarios, actividades, etc.).
Ejemplo: auth.routes.js
POST /api/auth/register
Flujo completo:
registerValidatorvalida nombre, email, passwordhandleValidationverifica errores- Verifica que el email no esté registrado
- Hashea la contraseña con
bcrypt - Inserta el usuario en la BD
- Genera un token JWT con
signToken() - Devuelve el token + datos del usuario
Request:
{
"nombre": "Juan",
"apellido": "Pérez",
"email": "juan@mail.com",
"genero": "M",
"password": "miPassword123"
}
Response (201):
{
"msg": "Usuario registrado con éxito",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id_usuario": 1,
"nombre": "Juan",
"apellido": "Pérez",
"email": "juan@mail.com",
"genero": "M"
}
}
POST /api/auth/login
Flujo completo:
loginValidatorvalida email y password- Busca el usuario por email en la BD
- Verifica que el usuario esté activo
- Compara la contraseña con
bcrypt.compare() - Genera token JWT
- Devuelve token + datos del usuario
Request:
{
"email": "juan@mail.com",
"password": "miPassword123"
}
Response (200):
{
"msg": "Login exitoso",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id_usuario": 1,
"nombre": "Juan",
...
}
}
Ver: src/routes/auth.routes.js para documentación línea por línea.
Diagrama de Componentes
┌─────────────────────────────────────────────────────────────┐
│ CLIENTE │
│ (Frontend - React/Vue) │
└────────────────────────┬────────────────────────────────────┘
│ HTTP Request
│ Authorization: Bearer <token>
↓
┌─────────────────────────────────────────────────────────────┐
│ SERVER.JS │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ MIDDLEWARES GLOBALES │ │
│ │ - CORS (permite frontend) │ │
│ │ - express.json() (parsea body) │ │
│ │ - morgan (logger) │ │
│ └──────────────────────────────────────────────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ ROUTER (Rutas) │
│ /api/auth → auth.routes.js │
│ /api/actividades → actividades.routes.js │
│ /api/categorias → categorias.routes.js │
│ ... │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ VALIDADORES + handleValidation │
│ - registerValidator (express-validator) │
│ - handleValidation (procesa errores) │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ MIDDLEWARES DE AUTH │
│ - requireAuth (verifica JWT) │
│ - requireAdmin (verifica rol admin) │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ LÓGICA DE LA RUTA │
│ - Consultas a BD (pool) │
│ - Procesamiento de datos │
│ - Generación de respuesta │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ BASE DE DATOS │
│ (MySQL) │
│ - usuarios, roles, actividades, insignias, etc. │
└─────────────────────────────────────────────────────────────┘
Conceptos Clave para Entender
1. Middleware
Funciones que se ejecutan ANTES de la lógica de la ruta. Se ejecutan en orden:
app.use(cors()); // 1. Permite CORS
app.use(express.json()); // 2. Parsea JSON
// ...
router.post('/login', loginValidator, handleValidation, async (req, res) => {
// 3. loginValidator → 4. handleValidation → 5. Esta función
});
2. JWT (JSON Web Token)
Token firmado que contiene información del usuario. Permite autenticación sin sesiones:
- Frontend: Guarda el token (localStorage/cookie)
- Cada petición: Envía el token en header
Authorization: Bearer <token> - Backend: Verifica el token y extrae datos del usuario
3. Bcrypt
Librería para hashear contraseñas de forma segura:
bcrypt.hash(password, 10)→ Hashea la contraseñabcrypt.compare(password, hash)→ Verifica si coinciden- NUNCA se guardan contraseñas en texto plano
4. Pool de Conexiones
En lugar de abrir/cerrar conexiones a MySQL constantemente, un pool mantiene conexiones abiertas y las reutiliza, mejorando el rendimiento.
5. Express Router
Permite modularizar las rutas:
// En server.js
app.use('/api/auth', authRoutes);
// En auth.routes.js
router.post('/login', ...); // Resulta en: POST /api/auth/login
Para Estudiantes
Cómo leer este código paso a paso
-
Empieza por
server.js: Entiende cómo se inicia el servidor y se registran las rutas. -
Lee
src/config/db.js: Aprende cómo se conecta a MySQL. -
Estudia
src/utils/jwt.js: Comprende cómo funciona la autenticación con JWT. -
Analiza
src/routes/auth.routes.js: Sigue el flujo completo de register/login. -
Revisa los middlewares: Entiende cómo
requireAuth,handleValidation, etc. protegen y validan. -
Explora otros módulos de rutas: Aplica lo aprendido a otras funcionalidades.
Preguntas frecuentes
¿Cómo funciona el login?
- Usuario envía email + password
- Backend busca el usuario en BD
- Compara password con bcrypt
- Genera un JWT con los datos del usuario
- Devuelve el JWT al frontend
- Frontend guarda el JWT y lo envía en cada petición
¿Cómo proteger una ruta?
router.get('/perfil', requireAuth, async (req, res) => {
// requireAuth verifica el JWT antes de ejecutar esto
const userId = req.user.id_usuario;
// ...
});
¿Cómo validar datos?
const miValidator = [
body('email').isEmail(),
body('edad').isInt({ min: 18 })
];
router.post('/ruta', miValidator, handleValidation, async (req, res) => {
// Si llega aquí, los datos ya están validados
});
Buenas Prácticas Implementadas
-
Seguridad:
- Contraseñas hasheadas con bcrypt
- Autenticación con JWT
- Validación de datos de entrada
- Variables sensibles en
.env
-
Código limpio:
- Comentarios explicativos
- Separación de responsabilidades (rutas, middlewares, validadores)
- Nombres descriptivos de variables y funciones
-
Arquitectura:
- Modular (cada funcionalidad en su archivo)
- Reutilizable (middlewares, validadores)
- Escalable (fácil agregar nuevas rutas)
Autor
Proyecto educativo desarrollado para aprendizaje de backend con Node.js y Express.
Licencia
Este es un proyecto de escuela sin licencia específica.