feat: cambiar clave desde la app (usuario logueado)
Nuevo PUT /api/auth/change-password: exige la clave actual (a diferencia de reset-password, que usa un token de correo sin sesion). Opcion "Cambiar clave" agregada al menu de usuario (popup), disponible para cualquier rol. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "project-linkedcorp-backend",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/server.js",
|
||||
|
||||
@@ -39,3 +39,9 @@ export const postResetPassword = asyncHandler(async (req, res) => {
|
||||
await authService.resetPassword(token, password);
|
||||
ok(res, { reset: true });
|
||||
});
|
||||
|
||||
export const putChangePassword = asyncHandler(async (req, res) => {
|
||||
const { currentPassword, newPassword } = req.body || {};
|
||||
await authService.changePassword(req.currentUser.id, currentPassword, newPassword);
|
||||
ok(res, { changed: true });
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import rateLimit from 'express-rate-limit';
|
||||
import { requireAuth } from '../../middleware/auth.js';
|
||||
import {
|
||||
postLogin, postLogout, getMe, postRegister, getVerifyEmail, postForgotPassword, postResetPassword,
|
||||
putChangePassword,
|
||||
} from './controller.js';
|
||||
|
||||
const router = Router();
|
||||
@@ -22,5 +23,6 @@ router.post('/forgot-password', loginLimiter, postForgotPassword);
|
||||
router.post('/reset-password', loginLimiter, postResetPassword);
|
||||
router.post('/logout', requireAuth, postLogout);
|
||||
router.get('/me', requireAuth, getMe);
|
||||
router.put('/change-password', requireAuth, loginLimiter, putChangePassword);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -170,3 +170,20 @@ export async function resetPassword(token, newPassword) {
|
||||
);
|
||||
await logAudit({ userId: user.id, action: 'reset_password', entityType: 'user', entityId: user.id });
|
||||
}
|
||||
|
||||
// Cambio de clave desde la app, con sesion activa (distinto del olvide-clave: exige la clave actual).
|
||||
export async function changePassword(userId, currentPassword, newPassword) {
|
||||
if (!currentPassword || !newPassword || newPassword.length < 8) {
|
||||
throw new HttpError(400, 'La clave actual y una clave nueva de al menos 8 caracteres son obligatorias');
|
||||
}
|
||||
const [rows] = await pool.query('SELECT password_hash FROM users WHERE id = ?', [userId]);
|
||||
const user = rows[0];
|
||||
if (!user) throw new HttpError(404, 'Usuario no encontrado');
|
||||
|
||||
const validPassword = await bcrypt.compare(currentPassword, user.password_hash);
|
||||
if (!validPassword) throw new HttpError(400, 'La clave actual no es correcta');
|
||||
|
||||
const passwordHash = await bcrypt.hash(newPassword, 12);
|
||||
await pool.query('UPDATE users SET password_hash = ? WHERE id = ?', [passwordHash, userId]);
|
||||
await logAudit({ userId, action: 'change_password', entityType: 'user', entityId: userId });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user