feat: version 3.0.0 -- Correcciones de auditoria de seguridad, accesibilidad y redundancia
Permisos (superadmin, viewer, busqueda, tareas recurrentes), bootstrap atomico, revocacion de JWT por version de sesion (028), control optimista de edicion (029), logo sin SVG + CSP, ingesta endurecida, correos escapados, borradores, paginacion de proyectos, accesibilidad de dialogos/controles e i18n. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,13 +17,13 @@ export async function requireAuth(req, res, next) {
|
||||
|
||||
// Revalidar en cada request que la cuenta siga activa (un JWT firmado no basta).
|
||||
const [rows] = await pool.query(
|
||||
`SELECT u.id, u.name, u.email, u.is_active, u.department_id, r.code AS role_code
|
||||
`SELECT u.id, u.name, u.email, u.is_active, u.session_version, u.department_id, r.code AS role_code
|
||||
FROM users u JOIN roles r ON r.id = u.role_id
|
||||
WHERE u.id = ? LIMIT 1`,
|
||||
[payload.sub]
|
||||
);
|
||||
const user = rows[0];
|
||||
if (!user || !user.is_active) return fail(res, 401, 'Cuenta inactiva o inexistente');
|
||||
if (!user || !user.is_active || payload.sv !== user.session_version) return fail(res, 401, 'Sesion invalida o revocada');
|
||||
|
||||
req.currentUser = {
|
||||
id: user.id,
|
||||
@@ -59,3 +59,5 @@ export const CAN_MANAGE_USERS = [ROLES.SUPERADMIN, ROLES.ADMIN];
|
||||
export const CAN_MANAGE_SMTP = [ROLES.SUPERADMIN];
|
||||
export const CAN_MANAGE_SETTINGS = [ROLES.SUPERADMIN];
|
||||
export const CAN_WRITE = [ROLES.SUPERADMIN, ROLES.ADMIN, ROLES.IT_MANAGER, ROLES.PROJECT_LEAD, ROLES.COLLABORATOR];
|
||||
export const CAN_EDIT_DEVICES = [ROLES.SUPERADMIN, ROLES.ADMIN, ROLES.IT_MANAGER];
|
||||
export const CAN_MANAGE_DEVICES = [ROLES.SUPERADMIN, ROLES.ADMIN];
|
||||
|
||||
@@ -4,7 +4,7 @@ import crypto from 'node:crypto';
|
||||
import multer from 'multer';
|
||||
import { env } from '../config/env.js';
|
||||
|
||||
const ALLOWED_MIME = new Set(['image/png', 'image/jpeg', 'image/webp', 'image/svg+xml']);
|
||||
const ALLOWED_MIME = new Set(['image/png', 'image/jpeg', 'image/webp']);
|
||||
|
||||
export const logoDir = path.join(env.storageRoot, 'branding');
|
||||
fs.mkdirSync(logoDir, { recursive: true });
|
||||
@@ -24,7 +24,7 @@ export const uploadLogo = multer({
|
||||
limits: { fileSize: 3 * 1024 * 1024 },
|
||||
fileFilter: (req, file, cb) => {
|
||||
if (!ALLOWED_MIME.has(file.mimetype)) {
|
||||
return cb(new Error('Tipo de archivo no permitido (usa PNG, JPG, WEBP o SVG)'));
|
||||
return cb(new Error('Tipo de archivo no permitido (usa PNG, JPG o WEBP)'));
|
||||
}
|
||||
cb(null, true);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user