import { requirePermission } from '$lib/server/auth/authorization'; import { getSessionUser } from '$lib/server/auth/session'; import { getDatabase } from '$lib/server/database'; import { getPagination } from '$lib/server/pagination'; import type { PageServerLoad } from './$types'; export const load: PageServerLoad = async ({ cookies, url }) => { await requirePermission(await getSessionUser(cookies), 'audit.view'); const database = await getDatabase(); const query = url.searchParams.get('q')?.trim().slice(0, 120) ?? ''; const category = url.searchParams.get('category')?.trim() ?? ''; const action = url.searchParams.get('action')?.trim() ?? ''; const conditions: string[] = []; const args: unknown[] = []; if (query) { conditions.push(`(audit_log.entity_id LIKE ? ESCAPE '\\' COLLATE NOCASE OR audit_log.before_json LIKE ? ESCAPE '\\' COLLATE NOCASE OR audit_log.after_json LIKE ? ESCAPE '\\' COLLATE NOCASE OR users.username LIKE ? ESCAPE '\\' COLLATE NOCASE OR user_profiles.display_name LIKE ? ESCAPE '\\' COLLATE NOCASE)`); const pattern = `%${query.replaceAll('%', '\\%').replaceAll('_', '\\_')}%`; args.push(pattern, pattern, pattern, pattern, pattern); } if (category === 'user') conditions.push("audit_log.entity_type IN ('user','user_access','user_moderation','identity')"); else if (category === 'access_policy') conditions.push("audit_log.entity_type IN ('role','role_management')"); else if (category) { conditions.push('audit_log.entity_type=?'); args.push(category); } if (action) { conditions.push('audit_log.action=?'); args.push(action); } const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : ''; const [total, categories, actions, summary] = await Promise.all([ (await database.prepare(`SELECT COUNT(*) AS total FROM audit_log JOIN users ON users.id=audit_log.actor_id LEFT JOIN user_profiles ON user_profiles.user_id=users.id ${where}`)).get(...args), (await database.prepare('SELECT entity_type,COUNT(*) AS count FROM audit_log GROUP BY entity_type ORDER BY entity_type')).all(), (await database.prepare('SELECT action,COUNT(*) AS count FROM audit_log GROUP BY action ORDER BY action')).all(), (await database.prepare(`SELECT COUNT(*) AS total, SUM(CASE WHEN entity_type='game_data' THEN 1 ELSE 0 END) AS game_data, SUM(CASE WHEN entity_type IN ('user','user_access','user_moderation','identity') THEN 1 ELSE 0 END) AS users, SUM(CASE WHEN entity_type IN ('role','role_management') THEN 1 ELSE 0 END) AS access FROM audit_log`)).get() ]); const pagination = getPagination(url, Number(total?.total ?? 0)); const entries = await (await database.prepare(`SELECT audit_log.*, COALESCE(user_profiles.display_name,users.username) AS actor_name,users.login_username AS actor_login FROM audit_log JOIN users ON users.id=audit_log.actor_id LEFT JOIN user_profiles ON user_profiles.user_id=users.id ${where} ORDER BY audit_log.created_at DESC LIMIT ? OFFSET ?`)).all(...args, pagination.perPage, pagination.offset); return { entries, categories, actions, summary, pagination, filters: { query, category, action } }; };