import express from 'express'; import bcrypt from 'bcrypt'; import { getRedisClient } from '../services/redis.js'; import { basicAuthMiddleware } from '../middlewares/auth.js'; const router = express.Router(); // Cambiar contraseña de usuario router.post('/change-password', basicAuthMiddleware, async (req, res) => { try { const redisClient = getRedisClient(); if (!redisClient) { return res.status(500).json({ error: 'Redis no está disponible' }); } const { currentPassword, newPassword } = req.body; const username = req.user.username; if (!currentPassword || !newPassword) { return res.status(400).json({ error: 'currentPassword y newPassword son requeridos' }); } if (newPassword.length < 6) { return res.status(400).json({ error: 'La nueva contraseña debe tener al menos 6 caracteres' }); } const userKey = `user:${username}`; const userData = await redisClient.hGetAll(userKey); if (!userData || !userData.passwordHash) { return res.status(404).json({ error: 'Usuario no encontrado' }); } // Verificar contraseña actual const match = await bcrypt.compare(currentPassword, userData.passwordHash); if (!match) { return res.status(401).json({ error: 'Contraseña actual incorrecta' }); } // Hashear nueva contraseña y actualizar const newPasswordHash = await bcrypt.hash(newPassword, 10); await redisClient.hSet(userKey, { ...userData, passwordHash: newPasswordHash, updatedAt: new Date().toISOString(), }); console.log(`✅ Contraseña actualizada para usuario: ${username}`); res.json({ success: true, message: 'Contraseña actualizada correctamente' }); } catch (error) { console.error('Error cambiando contraseña:', error); res.status(500).json({ error: error.message }); } }); // Obtener lista de usuarios (requiere autenticación admin) router.get('/', basicAuthMiddleware, async (req, res) => { try { const redisClient = getRedisClient(); if (!redisClient) { return res.status(500).json({ error: 'Redis no está disponible' }); } // Obtener todas las claves de usuarios const userKeys = await redisClient.keys('user:*'); const users = []; for (const key of userKeys) { const username = key.replace('user:', ''); const userData = await redisClient.hGetAll(key); if (userData && userData.username) { users.push({ username: userData.username, createdAt: userData.createdAt || null, updatedAt: userData.updatedAt || null, createdBy: userData.createdBy || null, }); } } // Ordenar por fecha de creación (más recientes primero) users.sort((a, b) => { const dateA = a.createdAt ? new Date(a.createdAt).getTime() : 0; const dateB = b.createdAt ? new Date(b.createdAt).getTime() : 0; return dateB - dateA; }); res.json({ users, total: users.length }); } catch (error) { console.error('Error obteniendo usuarios:', error); res.status(500).json({ error: error.message }); } }); // Crear nuevo usuario (requiere autenticación admin) router.post('/', basicAuthMiddleware, async (req, res) => { try { const redisClient = getRedisClient(); if (!redisClient) { return res.status(500).json({ error: 'Redis no está disponible' }); } const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ error: 'username y password son requeridos' }); } if (username.length < 3) { return res.status(400).json({ error: 'El nombre de usuario debe tener al menos 3 caracteres' }); } if (password.length < 6) { return res.status(400).json({ error: 'La contraseña debe tener al menos 6 caracteres' }); } const userKey = `user:${username}`; const userExists = await redisClient.exists(userKey); if (userExists) { return res.status(409).json({ error: 'El usuario ya existe' }); } // Hashear contraseña y crear usuario const passwordHash = await bcrypt.hash(password, 10); await redisClient.hSet(userKey, { username, passwordHash, createdAt: new Date().toISOString(), createdBy: req.user.username, }); console.log(`✅ Usuario creado: ${username} por ${req.user.username}`); res.json({ success: true, message: 'Usuario creado correctamente', username }); } catch (error) { console.error('Error creando usuario:', error); res.status(500).json({ error: error.message }); } }); // Eliminar usuario (requiere autenticación admin) router.delete('/:username', basicAuthMiddleware, async (req, res) => { try { const redisClient = getRedisClient(); if (!redisClient) { return res.status(500).json({ error: 'Redis no está disponible' }); } const { username } = req.params; const currentUser = req.user.username; // No permitir eliminar el propio usuario if (username === currentUser) { return res.status(400).json({ error: 'No puedes eliminar tu propio usuario' }); } const userKey = `user:${username}`; const userExists = await redisClient.exists(userKey); if (!userExists) { return res.status(404).json({ error: 'Usuario no encontrado' }); } // Eliminar usuario await redisClient.del(userKey); console.log(`✅ Usuario eliminado: ${username} por ${currentUser}`); res.json({ success: true, message: `Usuario ${username} eliminado correctamente` }); } catch (error) { console.error('Error eliminando usuario:', error); res.status(500).json({ error: error.message }); } }); export default router;