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:
@@ -0,0 +1,7 @@
|
||||
import { ok, asyncHandler } from '../../utils/http.js';
|
||||
import * as repo from './repository.js';
|
||||
|
||||
export const getAudit = asyncHandler(async (req, res) => {
|
||||
const { entityType, entityId } = req.query;
|
||||
ok(res, await repo.findAll({ entityType, entityId: entityId ? Number(entityId) : undefined }));
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { pool } from '../../config/db.js';
|
||||
|
||||
export async function findAll({ entityType, entityId } = {}) {
|
||||
const clauses = [];
|
||||
const params = [];
|
||||
if (entityType) { clauses.push('a.entity_type = ?'); params.push(entityType); }
|
||||
if (entityId) { clauses.push('a.entity_id = ?'); params.push(entityId); }
|
||||
const where = clauses.length ? `WHERE ${clauses.join(' AND ')}` : '';
|
||||
const [rows] = await pool.query(
|
||||
`SELECT a.id, a.user_id, u.name AS user_name, a.action, a.entity_type, a.entity_id, a.detail_json, a.created_at
|
||||
FROM audit_log a LEFT JOIN users u ON u.id = a.user_id
|
||||
${where} ORDER BY a.created_at DESC LIMIT 200`,
|
||||
params
|
||||
);
|
||||
return rows;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Router } from 'express';
|
||||
import { requireAuth, requireRole, ROLES } from '../../middleware/auth.js';
|
||||
import { getAudit } from './controller.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use(requireAuth, requireRole(ROLES.ADMIN, ROLES.IT_MANAGER));
|
||||
router.get('/', getAudit);
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user