import { and, count, desc, eq, type SQL } from 'drizzle-orm' import { AUDIT_ACTIONS } from '../../../shared/utils/audit' import { auditLog, users } from '../../db/schema' const PER_PAGE = 25 export default defineEventHandler(async (event) => { await requirePermission(event, 'audit.view') const q = getQuery(event) const page = Math.max(1, Math.floor(Number(q.page)) || 1) const action = String(q.action ?? '') const actorId = Number(q.user) const conditions: SQL[] = [] if ((AUDIT_ACTIONS as readonly string[]).includes(action)) conditions.push(eq(auditLog.action, action)) if (Number.isInteger(actorId) && actorId > 0) conditions.push(eq(auditLog.userId, actorId)) const where = conditions.length ? and(...conditions) : undefined const db = useDb() const [totalRow, rows] = await Promise.all([ db.select({ count: count() }).from(auditLog).where(where), db .select({ id: auditLog.id, action: auditLog.action, targetType: auditLog.targetType, targetId: auditLog.targetId, details: auditLog.details, createdAt: auditLog.createdAt, userId: auditLog.userId, userName: users.name, userColor: users.color, userAvatar: users.avatar, }) .from(auditLog) .leftJoin(users, eq(auditLog.userId, users.id)) .where(where) .orderBy(desc(auditLog.id)) .limit(PER_PAGE) .offset((page - 1) * PER_PAGE), ]) const total = totalRow[0]?.count ?? 0 return { items: rows.map(({ userAvatar, ...r }) => ({ ...r, userAvatarUrl: avatarUrl(userAvatar) })), total, perPage: PER_PAGE, pageCount: Math.max(1, Math.ceil(total / PER_PAGE)), } })