Files
project.linkedcorp.net/backend/src/modules/comments/controller.js
T
Milton Gonzalez 1d22adc42e 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>
2026-09-03 08:37:58 -05:00

25 lines
1.2 KiB
JavaScript

import { ok, fail, asyncHandler } from '../../utils/http.js';
import { HttpError } from '../../utils/http.js';
import { logAudit } from '../../utils/audit.js';
import { ROLES } from '../../middleware/auth.js';
import * as repo from './repository.js';
const VALID_ENTITY_TYPES = new Set(['project', 'activity']);
export const getComments = asyncHandler(async (req, res) => {
const { entityType, entityId } = req.query;
if (!VALID_ENTITY_TYPES.has(entityType) || !entityId) return fail(res, 400, 'entityType y entityId son obligatorios');
ok(res, await repo.findByEntity(entityType, Number(entityId)));
});
export const postComment = asyncHandler(async (req, res) => {
const { entityType, entityId, message } = req.body || {};
if (!VALID_ENTITY_TYPES.has(entityType) || !entityId || !message) {
throw new HttpError(400, 'entityType, entityId y message son obligatorios');
}
if (req.currentUser.roleCode === ROLES.VIEWER) throw new HttpError(403, 'Tu rol es de solo lectura');
const comment = await repo.create({ entityType, entityId, userId: req.currentUser.id, message });
await logAudit({ userId: req.currentUser.id, action: 'comment', entityType, entityId, detail: { commentId: comment.id } });
ok(res, comment, 201);
});