import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { AuditEventsRepository } from '../core-data/repositories/audit-events.repository'; import { AuditEvent, AuditSource } from '../database/entities'; import { sanitizeAuditData } from './audit-sanitizer'; export interface RecordAuditInput { actorUserId?: string | null; actorUsername?: string | null; action: string; entityType?: string | null; entityId?: string | null; requestId?: string | null; source?: AuditSource; ip?: string | null; userAgent?: string | null; beforeData?: Record | null; afterData?: Record | null; metadata?: Record | null; } @Injectable() export class AuditService { constructor(private readonly events: AuditEventsRepository) {} async record( input: RecordAuditInput, manager?: EntityManager, ): Promise { const eventInput = { actorUserId: input.actorUserId ?? null, actorUsername: input.actorUsername ?? null, action: input.action, entityType: input.entityType ?? null, entityId: input.entityId ?? null, requestId: input.requestId ?? null, source: input.source ?? AuditSource.WEB, ip: input.ip ?? null, userAgent: input.userAgent ?? null, beforeData: sanitizeAuditData(input.beforeData ?? null) as Record< string, unknown > | null, afterData: sanitizeAuditData(input.afterData ?? null) as Record< string, unknown > | null, metadata: sanitizeAuditData(input.metadata ?? null) as Record< string, unknown > | null, }; if (manager) { await manager.getRepository(AuditEvent).save(eventInput); return; } await this.events.save(this.events.create(eventInput)); } }