API RESTful desarrollada con Node.js + Express, PostgreSQL con Sequelize ORM, autenticación con JWT y subida de archivos con express-fileupload.
Proyecto integrador - Módulos 6, 7 y 8 del curso Full Stack JavaScript.
- Node.js + Express → Servidor web y framework backend
- Sequelize ORM + PostgreSQL → Base de datos relacional y ORM
- JSON Web Tokens (JWT) → Autenticación basada en tokens
- bcryptjs → Hasheo seguro de contraseñas
- express-fileupload → Subida de archivos al servidor
- dotenv → Variables de entorno
- Nodemon → Reinicio automático en desarrollo
git clone https://github.com/mvmv1428/ABP8.git
cd ABP8
npm installCopia y configura el archivo de entorno:
cp .env.example .envEdita .env con tus datos de PostgreSQL y una clave secreta para JWT:
DB_HOST=localhost
DB_PORT=5432
DB_NAME=abp_db
DB_USER=postgres
DB_PASS=tu_password
PORT=3000
JWT_SECRET=tu_clave_secreta_aquiInicia el servidor:
npm run devLa API estará disponible en http://localhost:3000
- Registrarse →
POST /api/auth/registercon nombre, email y password - Recibir token → La respuesta incluye un token JWT
- Usar el token → Enviar el token en el header de cada petición protegida:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Las rutas bajo /api/usuarios y /api/upload están protegidas porque manejan datos sensibles de usuarios y permiten modificar/eliminar registros. Sin autenticación, cualquiera podría acceder y manipular la información. Las rutas de auth (/api/auth/register y /api/auth/login) son públicas porque son las que generan el token.
El token se genera en el servidor y se envía al cliente en la respuesta JSON. El cliente (Postman, frontend, etc.) debe guardarlo y enviarlo en cada petición al header Authorization. El token expira en 2 horas por seguridad.
| Método | Ruta | Descripción |
|---|---|---|
| GET | / |
Página de inicio |
| GET | /status |
Estado del servidor |
| GET | /demo |
Cargar usuarios de prueba |
| POST | /api/auth/register |
Registrar nuevo usuario |
| POST | /api/auth/login |
Iniciar sesión |
| Método | Ruta | Descripción |
|---|---|---|
| GET | /api/usuarios |
Listar todos los usuarios |
| GET | /api/usuarios?nombre=xxx |
Buscar por nombre |
| GET | /api/usuarios?email=xxx |
Buscar por email |
| GET | /api/usuarios/:id |
Obtener usuario por ID (con historial) |
| POST | /api/usuarios |
Crear un usuario |
| PUT | /api/usuarios/:id |
Actualizar un usuario |
| DELETE | /api/usuarios/:id |
Eliminar un usuario |
| POST | /api/upload |
Subir un archivo (imagen) |
| POST | /api/upload/:userId |
Subir foto y asociar a un usuario |
| Método | Ruta | Descripción |
|---|---|---|
| GET | /usuarios |
Listar usuarios (ORM) |
| GET | /usuarios-sql |
Listar usuarios (SQL puro) |
| POST | /usuarios |
Crear usuario |
| PUT | /usuarios/:id |
Actualizar usuario |
| DELETE | /usuarios/:id |
Eliminar usuario |
| POST | /usuarios/historial |
Crear con transacción |
| GET | /usuarios/historial |
Usuarios con historial |
- Se usa express-fileupload para recibir archivos
- Se valida el tipo de archivo: solo imágenes (
.jpg,.jpeg,.png,.gif) - Se valida el tamaño: máximo 5MB
- Los archivos se guardan en la carpeta
/uploadscon nombre único - Se puede asociar una foto a un usuario en la BD (campo
foto)
ABP8/
├── app.js ← Servidor principal
├── config/
│ └── db.js ← Conexión a PostgreSQL
├── controllers/
│ ├── authController.js ← Registro y Login (JWT)
│ ├── apiUserController.js ← CRUD API estandarizado
│ ├── uploadController.js ← Subida de archivos
│ ├── userController.js ← CRUD original (Mod. 7)
│ ├── createUserController.js
│ ├── updateUserController.js
│ ├── deleteUserController.js
│ ├── historialController.js
│ ├── demoController.js
│ ├── homeController.js
│ └── statusController.js
├── middlewares/
│ ├── auth.js ← Middleware JWT
│ └── logger.js ← Logger de peticiones
├── models/
│ ├── User.js ← Modelo usuario (con password y foto)
│ ├── Historial.js ← Modelo historial
│ └── index.js ← Relaciones entre modelos
├── routes/
│ ├── authRoutes.js ← Rutas de autenticación
│ ├── apiUserRoutes.js ← Rutas API protegidas
│ ├── uploadRoutes.js ← Rutas de subida
│ ├── userRoutes.js ← Rutas originales
│ ├── homeRoutes.js
│ ├── statusRoutes.js
│ └── demoRoutes.js
├── uploads/ ← Archivos subidos
├── public/ ← Frontend estático
├── services/
│ └── logService.js ← Servicio de logs
├── logs/
│ └── log.txt ← Registro de peticiones
├── .env ← Variables de entorno
├── .env.example
├── .gitignore
└── package.json
npm run dev # Desarrollo con nodemon (reinicio automático)
npm start # Producción- Un User tiene muchos Historial (1:N)
- Un Historial pertenece a un User
Se implementa usando hasMany, belongsTo y consultas con include.
- Campos obligatorios (
allowNull: false) - Validación de email con formato correcto
- Longitud mínima/máxima en nombre, password y comentario
- Verificación de email duplicado en registro
- Contraseñas hasheadas con bcrypt (nunca texto plano)
- Tokens JWT con expiración de 2 horas
- Archivos: solo imágenes, máximo 5MB
Todas las rutas de la API (/api/*) responden con el mismo formato:
{
"status": "success" | "error",
"message": "Descripción del resultado",
"data": { ... } | null
}El uso de ORM como Sequelize facilita el desarrollo al abstraer las consultas SQL, permitiendo trabajar con objetos en lugar de queries manuales. Esto reduce errores, mejora la mantenibilidad y protege contra SQL Injection. Sin embargo, el SQL manual ofrece mayor control en consultas complejas.
- Módulo 6: Se construyó la base del servidor con Express, middlewares, archivos estáticos y logging.
- Módulo 7: Se integró PostgreSQL con Sequelize, se modelaron entidades con relaciones y se implementó CRUD completo.
- Módulo 8: Se expuso toda la funcionalidad como API RESTful, se agregó autenticación JWT para seguridad, y se implementó subida de archivos.
Cada módulo construyó sobre el anterior, y las decisiones de arquitectura (separar en controllers, routes, middlewares) permitieron agregar nuevas funcionalidades sin romper las existentes.
https://drive.google.com/drive/folders/134IpvXVCiutyVj-Ut_kbScQeOq2rPAjB?usp=sharing