import { Injectable } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { DbClient } from '../prisma/db-client'; import { AuditAction, AuditLog, Prisma } from '../../generated/prisma'; export interface RecordAuditLogInput { entityType: string; entityId: string; action: AuditAction; userId?: string; beforeData?: unknown; afterData?: unknown; } export interface AuditLogFilter { entityType?: string; entityId?: string; } @Injectable() export class AuditLogService { constructor(private readonly prisma: PrismaService) {} /** * With `tx` the entry commits or rolls back together with the change it * describes - no audited change without its entry, and no entry for a * change that never happened. */ async record( input: RecordAuditLogInput, tx?: Prisma.TransactionClient, ): Promise { const db: DbClient = tx ?? this.prisma; await db.auditLog.create({ data: { entityType: input.entityType, entityId: input.entityId, action: input.action, userId: input.userId, beforeData: input.beforeData as Prisma.InputJsonValue, afterData: input.afterData as Prisma.InputJsonValue, }, }); } async findAll(filter: AuditLogFilter = {}): Promise { return this.prisma.auditLog.findMany({ where: { entityType: filter.entityType, entityId: filter.entityId }, orderBy: { timestamp: 'desc' }, take: 200, }); } }