feat: add audit logging repository, service, and query API
Implements IAuditLogRepository with Prisma, AuditLogService with configurable retention policy and purge, and REST routes for querying/filtering audit logs at /api/v1/audit-logs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
70
src/mcpd/src/repositories/audit-log.repository.ts
Normal file
70
src/mcpd/src/repositories/audit-log.repository.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import type { PrismaClient, AuditLog, Prisma } from '@prisma/client';
|
||||
import type { IAuditLogRepository, AuditLogFilter } from './interfaces.js';
|
||||
|
||||
export class AuditLogRepository implements IAuditLogRepository {
|
||||
constructor(private readonly prisma: PrismaClient) {}
|
||||
|
||||
async findAll(filter?: AuditLogFilter): Promise<AuditLog[]> {
|
||||
const where = buildWhere(filter);
|
||||
return this.prisma.auditLog.findMany({
|
||||
where,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: filter?.limit ?? 100,
|
||||
skip: filter?.offset ?? 0,
|
||||
});
|
||||
}
|
||||
|
||||
async findById(id: string): Promise<AuditLog | null> {
|
||||
return this.prisma.auditLog.findUnique({ where: { id } });
|
||||
}
|
||||
|
||||
async create(data: {
|
||||
userId: string;
|
||||
action: string;
|
||||
resource: string;
|
||||
resourceId?: string;
|
||||
details?: Record<string, unknown>;
|
||||
}): Promise<AuditLog> {
|
||||
const createData: Prisma.AuditLogUncheckedCreateInput = {
|
||||
userId: data.userId,
|
||||
action: data.action,
|
||||
resource: data.resource,
|
||||
details: (data.details ?? {}) as Prisma.InputJsonValue,
|
||||
};
|
||||
if (data.resourceId !== undefined) {
|
||||
createData.resourceId = data.resourceId;
|
||||
}
|
||||
return this.prisma.auditLog.create({ data: createData });
|
||||
}
|
||||
|
||||
async count(filter?: AuditLogFilter): Promise<number> {
|
||||
const where = buildWhere(filter);
|
||||
return this.prisma.auditLog.count({ where });
|
||||
}
|
||||
|
||||
async deleteOlderThan(date: Date): Promise<number> {
|
||||
const result = await this.prisma.auditLog.deleteMany({
|
||||
where: { createdAt: { lt: date } },
|
||||
});
|
||||
return result.count;
|
||||
}
|
||||
}
|
||||
|
||||
function buildWhere(filter?: AuditLogFilter): Prisma.AuditLogWhereInput {
|
||||
const where: Prisma.AuditLogWhereInput = {};
|
||||
if (!filter) return where;
|
||||
|
||||
if (filter.userId !== undefined) where.userId = filter.userId;
|
||||
if (filter.action !== undefined) where.action = filter.action;
|
||||
if (filter.resource !== undefined) where.resource = filter.resource;
|
||||
if (filter.resourceId !== undefined) where.resourceId = filter.resourceId;
|
||||
|
||||
if (filter.since !== undefined || filter.until !== undefined) {
|
||||
const createdAt: Prisma.DateTimeFilter = {};
|
||||
if (filter.since !== undefined) createdAt.gte = filter.since;
|
||||
if (filter.until !== undefined) createdAt.lte = filter.until;
|
||||
where.createdAt = createdAt;
|
||||
}
|
||||
|
||||
return where;
|
||||
}
|
||||
Reference in New Issue
Block a user