85 lines
2.5 KiB
JavaScript
85 lines
2.5 KiB
JavaScript
import { randomUUID } from "node:crypto";
|
|
import { getPool } from "../db/pool";
|
|
function nowIso() {
|
|
return new Date().toISOString();
|
|
}
|
|
function mapAuditLog(row) {
|
|
return {
|
|
id: row.id,
|
|
actor_type: row.actor_type,
|
|
actor_id: row.actor_id || undefined,
|
|
action: row.action,
|
|
entity_type: row.entity_type,
|
|
entity_id: row.entity_id,
|
|
before_json: row.before_json || null,
|
|
after_json: row.after_json || null,
|
|
source_ip: row.source_ip || undefined,
|
|
request_id: row.request_id || undefined,
|
|
trace_id: row.trace_id || undefined,
|
|
created_at: row.created_at
|
|
};
|
|
}
|
|
export async function createAuditLog(payload) {
|
|
const { rows } = await getPool().query(`INSERT INTO audit_logs (
|
|
id,
|
|
actor_type,
|
|
actor_id,
|
|
action,
|
|
entity_type,
|
|
entity_id,
|
|
before_json,
|
|
after_json,
|
|
source_ip,
|
|
request_id,
|
|
trace_id,
|
|
created_at
|
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12)
|
|
RETURNING *`, [
|
|
randomUUID(),
|
|
payload.actor_type,
|
|
payload.actor_id || null,
|
|
payload.action,
|
|
payload.entity_type,
|
|
payload.entity_id,
|
|
payload.before_json || null,
|
|
payload.after_json || null,
|
|
payload.source_ip || null,
|
|
payload.request_id || null,
|
|
payload.trace_id || null,
|
|
nowIso()
|
|
]);
|
|
return mapAuditLog(rows[0]);
|
|
}
|
|
export async function listAuditLogs(filter) {
|
|
const clauses = [];
|
|
const params = [];
|
|
let i = 1;
|
|
if (filter?.entity_type) {
|
|
clauses.push(`entity_type = $${i++}`);
|
|
params.push(filter.entity_type);
|
|
}
|
|
if (filter?.entity_id) {
|
|
clauses.push(`entity_id = $${i++}`);
|
|
params.push(filter.entity_id);
|
|
}
|
|
if (filter?.action) {
|
|
clauses.push(`action = $${i++}`);
|
|
params.push(filter.action);
|
|
}
|
|
if (filter?.from) {
|
|
clauses.push(`created_at >= $${i++}`);
|
|
params.push(filter.from);
|
|
}
|
|
if (filter?.to) {
|
|
clauses.push(`created_at <= $${i++}`);
|
|
params.push(filter.to);
|
|
}
|
|
const limit = Math.min(Math.max(filter?.limit || 100, 1), 500);
|
|
const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
|
|
const { rows } = await getPool().query(`SELECT * FROM audit_logs ${where} ORDER BY created_at DESC LIMIT ${limit}`, params);
|
|
return rows.map(mapAuditLog);
|
|
}
|
|
export function toAuditLogPayload(auditLog) {
|
|
return { ...auditLog };
|
|
}
|