Files
CLProject/src/services/auditService.js
T
2026-04-19 21:14:16 +02:00

76 lines
1.8 KiB
JavaScript

import { query } from '../db/pool.js';
/*
* The audit service records every administrative mutation so the team can trace
* when configuration changed and what the previous value was. Each row captures
* the entity type (e.g. "image_rules"), the entity identifier, the action name,
* and JSON snapshots of the old and new values.
*/
export async function logAuditEvent({ entityType, entityCode, action, oldValue = null, newValue = null }) {
await query(
`
INSERT INTO audit_log (entity_type, entity_code, action, old_value_json, new_value_json)
VALUES (?, ?, ?, ?, ?)
`,
[
entityType,
entityCode,
action,
oldValue ? JSON.stringify(oldValue) : null,
newValue ? JSON.stringify(newValue) : null
]
);
}
export async function getAuditLog({ entityType, entityCode, limit = 50 } = {}) {
let sql = 'SELECT id, entity_type, entity_code, action, old_value_json, new_value_json, created_at FROM audit_log';
const params = [];
const clauses = [];
if (entityType) {
clauses.push('entity_type = ?');
params.push(entityType);
}
if (entityCode) {
clauses.push('entity_code = ?');
params.push(entityCode);
}
if (clauses.length) {
sql += ` WHERE ${clauses.join(' AND ')}`;
}
sql += ' ORDER BY id DESC LIMIT ?';
params.push(limit);
const rows = await query(sql, params);
return rows.map((row) => ({
id: row.id,
entityType: row.entity_type,
entityCode: row.entity_code,
action: row.action,
oldValue: safeParseJson(row.old_value_json),
newValue: safeParseJson(row.new_value_json),
createdAt: row.created_at
}));
}
function safeParseJson(value) {
if (value == null) {
return null;
}
if (typeof value === 'object') {
return value;
}
try {
return JSON.parse(value);
} catch {
return null;
}
}