chore: estructura inicial del MVP

Backend (Express + MariaDB) y frontend (React + Vite, identidad Fluent/Windows) con el
nucleo funcional: seguridad, organizacion, proyectos, actividades, subtareas, dependencias,
dashboard, calendario, gantt, comentarios, adjuntos, notificaciones in-app y catalogos.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-09-03 08:37:58 -05:00
commit 1d22adc42e
135 changed files with 10913 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
import jwt from 'jsonwebtoken';
import { env } from '../config/env.js';
import { pool } from '../config/db.js';
import { fail } from '../utils/http.js';
export async function requireAuth(req, res, next) {
const header = req.headers.authorization || '';
const token = header.startsWith('Bearer ') ? header.slice(7) : null;
if (!token) return fail(res, 401, 'No autenticado');
let payload;
try {
payload = jwt.verify(token, env.jwtSecret);
} catch {
return fail(res, 401, 'Token invalido o expirado');
}
// 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
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');
req.currentUser = {
id: user.id,
name: user.name,
email: user.email,
roleCode: user.role_code,
departmentId: user.department_id,
};
next();
}
export function requireRole(...roleCodes) {
return (req, res, next) => {
if (!req.currentUser) return fail(res, 401, 'No autenticado');
if (!roleCodes.includes(req.currentUser.roleCode)) {
return fail(res, 403, 'No tienes permisos para esta accion');
}
next();
};
}
export const ROLES = {
ADMIN: 'admin',
IT_MANAGER: 'it_manager',
PROJECT_LEAD: 'project_lead',
COLLABORATOR: 'collaborator',
VIEWER: 'viewer',
};
export const CAN_MANAGE_CATALOGS = [ROLES.ADMIN];
export const CAN_MANAGE_USERS = [ROLES.ADMIN];
export const CAN_WRITE = [ROLES.ADMIN, ROLES.IT_MANAGER, ROLES.PROJECT_LEAD, ROLES.COLLABORATOR];