Agenda de Contactos

Agenda de Contactos

EmpresaApp de Gestion Personal
Año2024
TipoFull Stack · MERN · RBAC
RolBackend · Frontend
Volver
01

Desarrollar una agenda de contactos multiusuario donde cada persona pueda gestionar sus propios contactos de forma privada, con un sistema de roles que permita a los administradores ver y gestionar todos los contactos del sistema, mientras que los usuarios regulares solo acceden a los suyos — todo con autenticacion segura y una interfaz intuitiva.

02

Desarrolle una aplicacion fullstack con React en frontend y Express + MongoDB en backend. El sistema implementa autenticacion con JWT, hash de contrasenas con bcrypt, RBAC con 2 roles (admin/user), control de visibilidad por ownership (cada usuario solo ve sus contactos), y CRUD completo de contactos con busqueda y filtros. La interfaz React consume la API con fetch y maneja el estado de autenticacion con Context API.

API REST con Express.js: rutas agrupadas por recurso (/api/auth, /api/contacts, /api/users) con middleware de autenticacion y autorizacion
MongoDB con Mongoose: schemas de User (name, email, password, role) y Contact (name, phone, email, address, notes, userId) con validaciones a nivel de modelo
Indices en MongoDB: unique en email de usuario, indice en userId de contactos para queries eficientes por ownership
JWT Authentication: token firmado con secret configurable, expiracion de 24 horas, payload con userId y role
Hash de contrasenas con bcrypt + salt rounds automaticos — las contrasenas nunca se almacenan en texto plano
Middleware de autenticacion: verifica el token en el header Authorization, decodifica el payload y adjunta el usuario al request
Middleware de autorizacion por rol: protege rutas admin-only verificando el role del usuario autenticado
RBAC con 2 roles: Admin (CRUD sobre todos los contactos y usuarios del sistema) y User (CRUD solo sobre sus propios contactos)
Control de visibilidad por ownership: las queries de contactos filtran automaticamente por userId del usuario autenticado — un usuario nunca puede ver contactos de otro
Ruta admin /api/users: listado de todos los usuarios registrados, solo accesible con role admin
Crear contacto: nombre (requerido), telefono, email, direccion, notas — se asocia automaticamente al userId del creador
Listar contactos: paginacion server-side con limit y skip, ordenados por nombre alfabeticamente
Busqueda de contactos: query parameter search que filtra por nombre, telefono o email usando regex case-insensitive en MongoDB
Editar contacto: PATCH con validacion de ownership — solo el creador puede modificar su contacto (o un admin)
Eliminar contacto: DELETE con validacion de ownership — confirmacion requerida en el frontend antes de ejecutar
Frontend React con Create React App: SPA con React Router para navegacion client-side entre login, registro, lista y detalle de contacto
Context API para estado global: AuthContext provee usuario, token, login(), logout() y isAuthenticated a toda la app
Formularios controlados con validacion client-side: campos requeridos, formato de email y telefono
Lista de contactos con buscador en tiempo real: el input de busqueda filtra localmente y dispara busqueda server-side con debounce
Interfaz responsive con CSS: mobile-first, cards de contacto con acciones rapidas (editar, eliminar, llamar), header con navegacion y logout
Vista admin: panel con listado de todos los usuarios del sistema, solo visible para usuarios con role admin
CORS configurado para el origen del frontend — rechaza requests de dominios no autorizados
Variables de entorno con dotenv: JWT_SECRET, MONGODB_URI, PORT — nunca hardcodeados en el codigo
Validacion server-side en cada endpoint: sanitizacion de inputs, verificacion de ObjectId valido, manejo de errores con status codes apropiados
FLUJO — Registro: [React] POST /api/auth/register {name, email, password} → [Express] valida campos requeridos → verifica email no existe en MongoDB (unique index) → bcrypt.hash(password, 10) → crea documento User {name, email, passwordHash, role: "user"} → Mongoose save() → response 201 {userId, name, email, role}
FLUJO — Login: [React] POST /api/auth/login {email, password} → [Express] busca user por email en MongoDB → bcrypt.compare(password, hash) → si falla: 401 → si pasa: jwt.sign({userId, role}, secret, {expiresIn: "24h"}) → response {token, user: {name, email, role}}
FLUJO — Control de ownership: [React] GET /api/contacts → [Auth Middleware] extrae JWT del header → decodifica userId → [ContactController] Contact.find({userId: decoded.userId}) → MongoDB retorna SOLO contactos de ese usuario → response 200 [{name, phone, email, ...}]. Un usuario NUNCA ve contactos de otro usuario. Si role==admin: Contact.find({}) retorna todos
FLUJO — Busqueda con regex: [React] input onChange con debounce 300ms → GET /api/contacts?search=juan&page=1&limit=10 → [Express] construye query MongoDB: {userId, $or: [{name: {$regex: "juan", $options: "i"}}, {phone: {$regex: "juan"}}, {email: {$regex: "juan", $options: "i"}}]} → .skip(0).limit(10).sort({name: 1}) → response con contactos que matchean + total count para paginacion
FLUJO — Admin vs User: [Request] DELETE /api/contacts/{id} → [Auth Middleware] extrae role del JWT → [ContactController] busca contacto por ID → si role=="user": verifica contact.userId == decoded.userId (ownership) → si no coincide: 403 → si role=="admin": permite eliminar cualquier contacto → Contact.deleteOne({_id: id}) → response 204
03
React
Express.js
MongoDB
Mongoose
JWT
bcrypt
Node.js
React Router
CSS
04
MERNMongo + Express + React + Node
RBACAdmin/User con ownership control
JWTAuth con bcrypt + token 24h
BusquedaRegex case-insensitive en MongoDB
PaginacionServer-side con limit/skip
ResponsiveMobile-first con CSS puro
Siguiente proyectoBoda Melanie & Antuan