implementar visualizacion de logs y seteo de usuario administrador
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
const auditService = require('./audit.service');
|
||||
const { sendSuccess } = require('../../utils/apiResponse');
|
||||
|
||||
const listMine = async (req, res, next) => {
|
||||
try {
|
||||
const result = await auditService.getEvents({
|
||||
userId: req.user.id,
|
||||
role: req.user.role,
|
||||
page: req.query.page,
|
||||
limit: req.query.limit,
|
||||
type: req.query.type,
|
||||
});
|
||||
return sendSuccess(res, result, 200);
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
const purgeMine = async (req, res, next) => {
|
||||
try {
|
||||
if (!req.body?.certPassword) {
|
||||
const error = new Error('Debes ingresar la contraseña de la firma registrada.');
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
const result = await auditService.purgeUserEvents({
|
||||
actorUserId: req.user.id,
|
||||
actorEmail: req.user.email,
|
||||
actorRole: req.user.role,
|
||||
certPassword: req.body.certPassword,
|
||||
ip: req.ip?.replace('::ffff:', '') || null,
|
||||
userAgent: req.headers['user-agent'] || null,
|
||||
});
|
||||
return sendSuccess(res, result, 200);
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
listMine,
|
||||
purgeMine,
|
||||
};
|
||||
@@ -30,15 +30,39 @@ const saveEvent = async (event) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getEvents = async ({ type, userId, limit = 100, offset = 0 } = {}) => {
|
||||
const getEvents = async ({ type, userId, limit = 100, offset = 0, types = [] } = {}) => {
|
||||
let sql = 'SELECT * FROM audit_logs WHERE 1=1';
|
||||
let countSql = 'SELECT COUNT(*) AS total FROM audit_logs WHERE 1=1';
|
||||
const params = [];
|
||||
const countParams = [];
|
||||
if (type) { sql += ' AND type = ?'; params.push(type); }
|
||||
if (userId) { sql += ' AND user_id = ?'; params.push(userId); }
|
||||
if (type) { countSql += ' AND type = ?'; countParams.push(type); }
|
||||
if (types.length > 0) {
|
||||
const placeholders = types.map(() => '?').join(', ');
|
||||
sql += ` AND type IN (${placeholders})`;
|
||||
countSql += ` AND type IN (${placeholders})`;
|
||||
params.push(...types);
|
||||
countParams.push(...types);
|
||||
}
|
||||
if (userId) {
|
||||
sql += ' AND user_id = ?';
|
||||
countSql += ' AND user_id = ?';
|
||||
params.push(userId);
|
||||
countParams.push(userId);
|
||||
}
|
||||
sql += ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
|
||||
params.push(limit, offset);
|
||||
const [rows] = await db.execute(sql, params);
|
||||
return rows;
|
||||
const [countRows] = await db.execute(countSql, countParams);
|
||||
return {
|
||||
rows,
|
||||
total: countRows[0]?.total || 0,
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = { saveEvent, getEvents };
|
||||
const deleteEventsByUserId = async (userId) => {
|
||||
const [result] = await db.execute('DELETE FROM audit_logs WHERE user_id = ?', [userId]);
|
||||
return result.affectedRows || 0;
|
||||
};
|
||||
|
||||
module.exports = { saveEvent, getEvents, deleteEventsByUserId };
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
const express = require('express');
|
||||
const authenticate = require('../../middlewares/authenticate');
|
||||
const auditController = require('./audit.controller');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/mine', authenticate, auditController.listMine);
|
||||
router.post('/mine/purge', authenticate, auditController.purgeMine);
|
||||
|
||||
module.exports = router;
|
||||
@@ -1,11 +1,74 @@
|
||||
const auditRepository = require('./audit.repository');
|
||||
const certificatesService = require('../certificates/certificates.service');
|
||||
|
||||
const logEvent = async ({ type, userId = null, email = null, ip = null, userAgent = null, metadata = null } = {}) => {
|
||||
await auditRepository.saveEvent({ type, userId, email, ip, userAgent, metadata });
|
||||
};
|
||||
|
||||
const getEvents = async (filters) => {
|
||||
return auditRepository.getEvents(filters);
|
||||
const ADMIN_VISIBLE_TYPES = ['AUDIT_LOGS_PURGED'];
|
||||
|
||||
const getEvents = async (filters = {}) => {
|
||||
const limit = Math.min(Math.max(Number(filters.limit) || 15, 1), 50);
|
||||
const page = Math.max(Number(filters.page) || 1, 1);
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
const types = filters.role === 'admin' ? ADMIN_VISIBLE_TYPES : [];
|
||||
|
||||
const result = await auditRepository.getEvents({
|
||||
type: filters.type || null,
|
||||
userId: filters.role === 'admin' ? null : (filters.userId || null),
|
||||
limit,
|
||||
offset,
|
||||
types,
|
||||
});
|
||||
|
||||
return {
|
||||
rows: result.rows.map((row) => ({
|
||||
...row,
|
||||
metadata: row.metadata ? JSON.parse(row.metadata) : null,
|
||||
})),
|
||||
pagination: {
|
||||
page,
|
||||
limit,
|
||||
total: result.total,
|
||||
totalPages: Math.max(1, Math.ceil(result.total / limit)),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = { logEvent, getEvents };
|
||||
const purgeUserEvents = async ({ actorUserId, actorEmail, actorRole, certPassword, ip, userAgent }) => {
|
||||
if (actorRole === 'admin') {
|
||||
const error = new Error('La cuenta administradora no puede eliminar logs.');
|
||||
error.statusCode = 403;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const activeCertificate = await certificatesService.getLatestActiveForUser(actorUserId);
|
||||
if (!activeCertificate) {
|
||||
const error = new Error('No existe un certificado activo asociado a esta cuenta.');
|
||||
error.statusCode = 404;
|
||||
throw error;
|
||||
}
|
||||
|
||||
await certificatesService.loadForSigning(activeCertificate.id, actorUserId, certPassword);
|
||||
|
||||
const deletedCount = await auditRepository.deleteEventsByUserId(actorUserId);
|
||||
|
||||
await auditRepository.saveEvent({
|
||||
type: 'AUDIT_LOGS_PURGED',
|
||||
userId: null,
|
||||
email: actorEmail,
|
||||
ip,
|
||||
userAgent,
|
||||
metadata: {
|
||||
purgedUserId: actorUserId,
|
||||
purgedEmail: actorEmail,
|
||||
deletedCount,
|
||||
certificateId: activeCertificate.id,
|
||||
},
|
||||
});
|
||||
|
||||
return { deletedCount };
|
||||
};
|
||||
|
||||
module.exports = { logEvent, getEvents, purgeUserEvents };
|
||||
|
||||
Reference in New Issue
Block a user