Express
Tutorial Express: Registro de usuarios
Aprende a crear un sistema de registro de usuarios en Express 5 con validación, manejo de errores y almacenamiento simulado.
Aprende Express y certifícateImplementar registro de usuarios
El registro de usuarios es una funcionalidad fundamental en cualquier aplicación web que requiera autenticación. En Express 5, podemos implementar un sistema de registro completo utilizando únicamente las capacidades nativas del framework, sin necesidad de librerías externas adicionales.
Para crear un endpoint de registro efectivo, necesitamos manejar la validación de datos, el almacenamiento temporal de usuarios y las respuestas HTTP apropiadas. Comenzaremos con una implementación básica que simule el almacenamiento en memoria.
Estructura básica del endpoint de registro
El endpoint de registro debe manejar peticiones POST y procesar los datos del usuario de forma segura:
import express from 'express';
const app = express();
const usuarios = []; // Almacenamiento temporal en memoria
// Middleware para parsear JSON
app.use(express.json());
app.post('/api/registro', (req, res) => {
const { nombre, email, password } = req.body;
// Validación básica de campos requeridos
if (!nombre || !email || !password) {
return res.status(400).json({
error: 'Todos los campos son obligatorios',
campos: ['nombre', 'email', 'password']
});
}
// Verificar si el usuario ya existe
const usuarioExistente = usuarios.find(user => user.email === email);
if (usuarioExistente) {
return res.status(409).json({
error: 'El usuario ya está registrado',
email: email
});
}
// Crear nuevo usuario
const nuevoUsuario = {
id: usuarios.length + 1,
nombre,
email,
password, // En producción esto debe estar hasheado
fechaRegistro: new Date().toISOString()
};
usuarios.push(nuevoUsuario);
// Respuesta exitosa (sin incluir la contraseña)
const { password: _, ...usuarioRespuesta } = nuevoUsuario;
res.status(201).json({
mensaje: 'Usuario registrado exitosamente',
usuario: usuarioRespuesta
});
});
Validación avanzada de datos
Una implementación robusta requiere validaciones más específicas para garantizar la calidad de los datos:
// Función para validar formato de email
function validarEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
// Función para validar fortaleza de contraseña
function validarPassword(password) {
return password.length >= 8 &&
/[A-Z]/.test(password) &&
/[a-z]/.test(password) &&
/\d/.test(password);
}
app.post('/api/registro', (req, res) => {
const { nombre, email, password } = req.body;
// Validaciones específicas
const errores = [];
if (!nombre || nombre.trim().length < 2) {
errores.push('El nombre debe tener al menos 2 caracteres');
}
if (!email || !validarEmail(email)) {
errores.push('El email debe tener un formato válido');
}
if (!password || !validarPassword(password)) {
errores.push('La contraseña debe tener al menos 8 caracteres, una mayúscula, una minúscula y un número');
}
if (errores.length > 0) {
return res.status(400).json({
error: 'Datos de registro inválidos',
detalles: errores
});
}
// Continuar con el registro...
});
Manejo de errores y respuestas consistentes
El manejo de errores debe ser consistente y proporcionar información útil tanto para el cliente como para el debugging:
// Middleware de manejo de errores para registro
function manejarErrorRegistro(error, req, res, next) {
console.error('Error en registro:', error);
if (error.type === 'entity.parse.failed') {
return res.status(400).json({
error: 'Formato JSON inválido',
mensaje: 'Verifica la sintaxis del JSON enviado'
});
}
res.status(500).json({
error: 'Error interno del servidor',
mensaje: 'No se pudo completar el registro'
});
}
// Endpoint con manejo completo de errores
app.post('/api/registro', async (req, res, next) => {
try {
const { nombre, email, password } = req.body;
// Normalizar datos de entrada
const datosNormalizados = {
nombre: nombre?.trim(),
email: email?.toLowerCase().trim(),
password: password
};
// Validaciones y registro...
res.status(201).json({
exito: true,
mensaje: 'Usuario registrado correctamente',
usuario: usuarioRespuesta
});
} catch (error) {
next(error);
}
});
app.use(manejarErrorRegistro);
Implementación con almacenamiento persistente simulado
Para simular un almacenamiento más realista, podemos implementar funciones que emulen operaciones de base de datos:
import fs from 'fs/promises';
import path from 'path';
const ARCHIVO_USUARIOS = path.join(process.cwd(), 'usuarios.json');
// Funciones de almacenamiento
async function cargarUsuarios() {
try {
const datos = await fs.readFile(ARCHIVO_USUARIOS, 'utf8');
return JSON.parse(datos);
} catch (error) {
return []; // Si no existe el archivo, devolver array vacío
}
}
async function guardarUsuarios(usuarios) {
await fs.writeFile(ARCHIVO_USUARIOS, JSON.stringify(usuarios, null, 2));
}
async function buscarUsuarioPorEmail(email) {
const usuarios = await cargarUsuarios();
return usuarios.find(user => user.email === email);
}
// Endpoint con almacenamiento persistente
app.post('/api/registro', async (req, res, next) => {
try {
const { nombre, email, password } = req.body;
// Verificar usuario existente
const usuarioExistente = await buscarUsuarioPorEmail(email.toLowerCase());
if (usuarioExistente) {
return res.status(409).json({
error: 'Email ya registrado',
mensaje: 'Este email ya está asociado a una cuenta'
});
}
// Crear nuevo usuario
const usuarios = await cargarUsuarios();
const nuevoUsuario = {
id: Date.now(), // ID único basado en timestamp
nombre: nombre.trim(),
email: email.toLowerCase().trim(),
password: password, // Temporal - se hasheará en la siguiente lección
fechaRegistro: new Date().toISOString(),
activo: true
};
usuarios.push(nuevoUsuario);
await guardarUsuarios(usuarios);
// Respuesta sin contraseña
const { password: _, ...usuarioSeguro } = nuevoUsuario;
res.status(201).json({
exito: true,
mensaje: 'Registro completado exitosamente',
usuario: usuarioSeguro
});
} catch (error) {
next(error);
}
});
Middleware de validación reutilizable
Para mantener el código organizado y reutilizable, podemos crear middleware específico para validaciones:
// Middleware de validación de registro
function validarDatosRegistro(req, res, next) {
const { nombre, email, password } = req.body;
const errores = [];
// Validar presencia de campos
if (!nombre?.trim()) errores.push('Nombre es obligatorio');
if (!email?.trim()) errores.push('Email es obligatorio');
if (!password) errores.push('Contraseña es obligatoria');
// Validar formatos
if (email && !validarEmail(email)) {
errores.push('Formato de email inválido');
}
if (password && !validarPassword(password)) {
errores.push('Contraseña no cumple los requisitos de seguridad');
}
if (errores.length > 0) {
return res.status(400).json({
error: 'Datos de entrada inválidos',
detalles: errores
});
}
// Normalizar datos para el siguiente middleware
req.datosRegistro = {
nombre: nombre.trim(),
email: email.toLowerCase().trim(),
password: password
};
next();
}
// Uso del middleware
app.post('/api/registro', validarDatosRegistro, async (req, res, next) => {
try {
const { nombre, email, password } = req.datosRegistro;
// Lógica de registro simplificada
const usuarioExistente = await buscarUsuarioPorEmail(email);
if (usuarioExistente) {
return res.status(409).json({
error: 'Usuario ya existe'
});
}
// Crear y guardar usuario...
} catch (error) {
next(error);
}
});
Esta implementación proporciona una base sólida para el registro de usuarios en Express 5, manejando validaciones, errores y almacenamiento de forma estructurada. El código está preparado para integrar el hashing de contraseñas en la siguiente lección, manteniendo la arquitectura limpia y escalable.
Otras lecciones de Express
Accede a todas las lecciones de Express y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Expressjs
Introducción Y Entorno
Instalación De Express
Introducción Y Entorno
Estados Http
Routing
Métodos Delete
Routing
Parámetros Y Query Strings
Routing
Métodos Get
Routing
Ejercicios de programación de Express
Evalúa tus conocimientos de esta lección Registro de usuarios con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.