feat: version 2.7.0 -- menu Contraseñas (repositorio de credenciales privado)
Nuevo modulo backend/src/modules/vault/: contraseña y notas cifradas en el servidor (AES-256-GCM, mismo mecanismo ya usado para la clave SMTP). Acceso al menu protegido con un PIN de 4 digitos independiente del login (token corto propio, header X-Vault-Token, nunca el JWT de sesion). El PIN no participa del cifrado -- cambiarlo o restablecerlo por correo nunca afecta las contraseñas ya guardadas. Privado por usuario, sin excepcion. Cada accion sensible (crear/editar/eliminar/ revelar/desbloquear) queda en audit_log. Compartir con otro usuario queda para una proxima version. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { Router } from 'express';
|
||||
import rateLimit from 'express-rate-limit';
|
||||
import { requireAuth } from '../../middleware/auth.js';
|
||||
import { requireVaultUnlock } from './middleware.js';
|
||||
import {
|
||||
getStatus, postPin, postUnlock, postChangePin, postForgotPin, postResetPin,
|
||||
getEntries, getEntry, postEntry, putEntry, deleteEntry,
|
||||
} from './controller.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// PIN de 4 digitos: 10,000 combinaciones -- sin este limiter seria trivial de forzar.
|
||||
const unlockLimiter = rateLimit({ windowMs: 15 * 60 * 1000, limit: 8, standardHeaders: true, legacyHeaders: false });
|
||||
|
||||
// Publico, como auth/reset-password: el link del correo puede abrirse sin sesion activa.
|
||||
router.post('/reset-pin', unlockLimiter, postResetPin);
|
||||
|
||||
router.use(requireAuth);
|
||||
router.get('/status', getStatus);
|
||||
router.post('/pin', postPin);
|
||||
router.post('/unlock', unlockLimiter, postUnlock);
|
||||
router.post('/change-pin', unlockLimiter, postChangePin);
|
||||
router.post('/forgot-pin', unlockLimiter, postForgotPin);
|
||||
|
||||
router.get('/entries', requireVaultUnlock, getEntries);
|
||||
router.get('/entries/:id', requireVaultUnlock, getEntry);
|
||||
router.post('/entries', requireVaultUnlock, postEntry);
|
||||
router.put('/entries/:id', requireVaultUnlock, putEntry);
|
||||
router.delete('/entries/:id', requireVaultUnlock, deleteEntry);
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user