fix: version 2.5.0 -- compartir proyectos con permisos reales (Lectura/Escritura)
Bug de seguridad real corregido: cualquier usuario autenticado veia TODOS los proyectos (listado, detalle, actividades, tareas, comentarios, adjuntos, KPIs del panel), sin importar si era miembro. Ahora nadie ve un proyecto ajeno sin que su dueno se lo comparta -- los roles de administracion (superadmin/admin/it_manager) mantienen visibilidad total para soporte. Nuevo modelo de permisos por proyecto, simple y no granular: - Solo el dueno original puede compartir un proyecto (agregar/quitar miembros, cambiar su nivel) -- ni un admin del proyecto ni un rol global pueden hacerlo por el. - Dos niveles: Lectura (solo ver) y Escritura (crear/editar/eliminar actividades y tareas -- nunca el proyecto en si: no lo borra, no edita sus datos, no crea proyectos nuevos). Actividades y tareas pasan a borrado logico (antes se borraban fisico sin poder recuperar) -- nueva papelera por proyecto con restaurar. Incluye tambien el filtro "Usuario" en Proyectos (probado en dev en un paso anterior), que va de la mano con este cambio de visibilidad. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,12 +2,22 @@ import { ok, fail, asyncHandler } from '../../utils/http.js';
|
||||
import * as repo from './repository.js';
|
||||
import { listByProject } from '../activities/service.js';
|
||||
import { dueStatus } from '../../utils/dates.js';
|
||||
import { ROLES } from '../../middleware/auth.js';
|
||||
|
||||
const FULL_ACCESS_ROLES = [ROLES.SUPERADMIN, ROLES.ADMIN, ROLES.IT_MANAGER];
|
||||
|
||||
// Mismo criterio que projects/service.js#listProjects: los roles de administracion ven todo el
|
||||
// panel; el resto solo cuenta/lista lo de proyectos donde es miembro.
|
||||
function memberFilterFor(currentUser) {
|
||||
return FULL_ACCESS_ROLES.includes(currentUser.roleCode) ? null : currentUser.id;
|
||||
}
|
||||
|
||||
export const getSummary = asyncHandler(async (req, res) => {
|
||||
const memberUserId = memberFilterFor(req.currentUser);
|
||||
const [kpis, myActivities, byStatus] = await Promise.all([
|
||||
repo.summary(),
|
||||
repo.myPendingActivities(req.currentUser.id),
|
||||
repo.projectsByStatus(),
|
||||
repo.summary(memberUserId),
|
||||
repo.myPendingActivities(req.currentUser.id, memberUserId),
|
||||
repo.projectsByStatus(memberUserId),
|
||||
]);
|
||||
ok(res, {
|
||||
kpis,
|
||||
@@ -22,12 +32,12 @@ export const getCalendar = asyncHandler(async (req, res) => {
|
||||
const start = `${month}-01`;
|
||||
const [year, m] = month.split('-').map(Number);
|
||||
const end = new Date(year, m, 0).toISOString().slice(0, 10);
|
||||
const items = await repo.calendarActivities(start, end);
|
||||
const items = await repo.calendarActivities(start, end, memberFilterFor(req.currentUser));
|
||||
ok(res, items.map((a) => ({ ...a, dueStatus: dueStatus(a.due_date, a.status_is_closed) })));
|
||||
});
|
||||
|
||||
export const getGantt = asyncHandler(async (req, res) => {
|
||||
const activities = await listByProject(Number(req.params.id));
|
||||
const activities = await listByProject(Number(req.params.id), req.currentUser);
|
||||
ok(res, activities.map((a) => ({
|
||||
id: a.id, code: a.code, name: a.name, startDate: a.start_date, dueDate: a.due_date,
|
||||
progressPct: a.progress_pct, isMilestone: !!a.is_milestone, responsibleName: a.responsible_name,
|
||||
|
||||
Reference in New Issue
Block a user