import { desc, eq } from "drizzle-orm"; import { getDatabase } from "@/modules/core/server/db"; import { auditLogs } from "@/modules/core/server/schema"; import type { AuditLog, AuditResult, PublicAccount } from "@/modules/core/types"; type AuditInput = { actor?: PublicAccount; organizationId?: string; action: string; targetType: string; targetId?: string; result: AuditResult; reason: string; }; function toAuditLog(row: typeof auditLogs.$inferSelect): AuditLog { return { id: row.id, organizationId: row.organizationId ?? undefined, timestamp: row.timestamp.toISOString(), actorAccountId: row.actorAccountId ?? undefined, actorEmail: row.actorEmail ?? undefined, action: row.action, targetType: row.targetType, targetId: row.targetId ?? undefined, result: row.result, reason: row.reason, }; } export async function recordAuditLog(input: AuditInput): Promise { const database = getDatabase(); const rows = await database .insert(auditLogs) .values({ organizationId: input.organizationId, actorAccountId: input.actor?.id, actorEmail: input.actor?.email, action: input.action, targetType: input.targetType, targetId: input.targetId, result: input.result, reason: input.reason, }) .returning(); const row = rows[0]; if (!row) { throw new Error("审计日志写入失败"); } return toAuditLog(row); } export async function listAuditLogs(params: { organizationId?: string; limit?: number }): Promise { const database = getDatabase(); const limit = params.limit ?? 100; const rows = params.organizationId ? await database .select() .from(auditLogs) .where(eq(auditLogs.organizationId, params.organizationId)) .orderBy(desc(auditLogs.timestamp)) .limit(limit) : await database.select().from(auditLogs).orderBy(desc(auditLogs.timestamp)).limit(limit); return rows.map(toAuditLog); }