76 lines
1.8 KiB
JavaScript
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;
|
|
}
|
|
}
|