48 lines
3.1 KiB
TypeScript
48 lines
3.1 KiB
TypeScript
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 } };
|
|
};
|