feat: nombre y logo de empresa configurables (solo dev, no desplegado a prod)
Nueva marca configurable desde Configuracion -> Empresa (solo superadmin): nombre y logo, guardados en system_settings (mismo patron que SMTP, sin tabla nueva). Nuevo endpoint publico GET /api/company (+ /logo) para que login/registro/recuperacion de clave puedan mostrar la marca antes de iniciar sesion. Sin configurar, se ve "LinkedCorp" y el logo estatico de siempre. Probado en dev (build + Playwright: panel de Configuracion, sidebar expandido/compacto, login publico), sin desplegar a produccion por pedido explicito del usuario -- este commit sirve de punto de control en git antes de decidir el despliegue. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -57,4 +57,5 @@ export const ROLES = {
|
||||
export const CAN_MANAGE_CATALOGS = [ROLES.SUPERADMIN];
|
||||
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];
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
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']);
|
||||
|
||||
export const logoDir = path.join(env.storageRoot, 'branding');
|
||||
fs.mkdirSync(logoDir, { recursive: true });
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => cb(null, logoDir),
|
||||
// Nombre generado por el servidor (evita colisiones/path traversal) y sirve de version para
|
||||
// el cache-busting del logo publico (cambia en cada subida).
|
||||
filename: (req, file, cb) => {
|
||||
const ext = path.extname(file.originalname).slice(0, 10);
|
||||
cb(null, `logo-${Date.now()}-${crypto.randomBytes(6).toString('hex')}${ext}`);
|
||||
},
|
||||
});
|
||||
|
||||
export const uploadLogo = multer({
|
||||
storage,
|
||||
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)'));
|
||||
}
|
||||
cb(null, true);
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user