Go to file
Roberto Castellanos 35fe8db1f9 Agregango archivos necesarios para auth 2025-10-19 22:12:18 -06:00
node_modules first commit 2025-10-19 12:24:23 -06:00
src Agregango archivos necesarios para auth 2025-10-19 22:12:18 -06:00
.env first commit 2025-10-19 12:24:23 -06:00
README.md first commit 2025-10-19 12:24:23 -06:00
package-lock.json first commit 2025-10-19 12:24:23 -06:00
package.json first commit 2025-10-19 12:24:23 -06:00
server.js validado seguridad 2025-10-19 22:10:45 -06:00
test-jwt.js first commit 2025-10-19 12:24:23 -06:00

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

  1. Tecnologías Utilizadas
  2. Estructura del Proyecto
  3. Configuración Inicial
  4. Arquitectura y Flujo de Datos
  5. Endpoints Disponibles
  6. 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 roles
  • categorias: Categorías de actividades
  • actividades: Actividades del sistema
  • insignias: Insignias/badges del sistema de gamificación
  • metas: Metas/objetivos de usuarios
  • niveles: Niveles del sistema de progreso
  • notificaciones: Sistema de notificaciones
  • agenda: Calendario/planificación de actividades
  • registro_actividad: Registro de actividades completadas
  • usuario_metricas: Estadísticas de usuarios
  • usuario_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 -
PUT /api/auth/me/profile Actualizar perfil { nombre?, apellido? }
PUT /api/auth/me/password Cambiar contraseña { 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:

  1. Carga las variables de entorno con dotenv
  2. Configura Express y los middlewares globales (CORS, body parser, logger)
  3. Registra todas las rutas de la aplicación
  4. 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áneas
  • namedPlaceholders: true → Permite usar :nombre en 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:

  1. signToken(payload, expiresIn)

    • Genera un token JWT firmado
    • Usado en register/login para crear tokens
    • Incluye datos del usuario (id_usuario, email)
  2. verifyTokenPayload(token)

    • Verifica que un token sea válido
    • Extrae y devuelve el payload decodificado
  3. 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.user con 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 Request con 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:

  1. Verifica que req.user exista (debe usarse DESPUÉS de requireAuth)
  2. Consulta la BD para verificar si el usuario tiene rol 'admin'
  3. 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:

  1. Se aplica como middleware en la ruta
  2. express-validator verifica cada campo
  3. handleValidation recoge 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:

  1. registerValidator valida nombre, email, password
  2. handleValidation verifica errores
  3. Verifica que el email no esté registrado
  4. Hashea la contraseña con bcrypt
  5. Inserta el usuario en la BD
  6. Genera un token JWT con signToken()
  7. 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:

  1. loginValidator valida email y password
  2. Busca el usuario por email en la BD
  3. Verifica que el usuario esté activo
  4. Compara la contraseña con bcrypt.compare()
  5. Genera token JWT
  6. 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ña
  • bcrypt.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

  1. Empieza por server.js: Entiende cómo se inicia el servidor y se registran las rutas.

  2. Lee src/config/db.js: Aprende cómo se conecta a MySQL.

  3. Estudia src/utils/jwt.js: Comprende cómo funciona la autenticación con JWT.

  4. Analiza src/routes/auth.routes.js: Sigue el flujo completo de register/login.

  5. Revisa los middlewares: Entiende cómo requireAuth, handleValidation, etc. protegen y validan.

  6. Explora otros módulos de rutas: Aplica lo aprendido a otras funcionalidades.

Preguntas frecuentes

¿Cómo funciona el login?

  1. Usuario envía email + password
  2. Backend busca el usuario en BD
  3. Compara password con bcrypt
  4. Genera un JWT con los datos del usuario
  5. Devuelve el JWT al frontend
  6. 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

  1. Seguridad:

    • Contraseñas hasheadas con bcrypt
    • Autenticación con JWT
    • Validación de datos de entrada
    • Variables sensibles en .env
  2. Código limpio:

    • Comentarios explicativos
    • Separación de responsabilidades (rutas, middlewares, validadores)
    • Nombres descriptivos de variables y funciones
  3. 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.