| import { NextResponse } from 'next/server'; |
| import { requireAdmin } from '@/lib/auth-middleware'; |
| import { queryAudit, type AuditAction } from '@/lib/audit'; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| export const runtime = 'nodejs'; |
| export const dynamic = 'force-dynamic'; |
|
|
| const ALLOWED_ACTIONS = new Set<AuditAction>([ |
| 'login', |
| 'login_failed', |
| 'logout', |
| 'register', |
| 'verify_email', |
| 'password_reset_request', |
| 'password_reset', |
| 'password_change', |
| 'delete_account', |
| 'admin_login', |
| 'admin_action', |
| 'admin_user_delete', |
| 'admin_user_reset_password', |
| 'admin_config_update', |
| 'token_rotate', |
| 'chat', |
| 'scan', |
| 'health_data_write', |
| 'health_data_delete', |
| 'settings_update', |
| 'export_data', |
| ]); |
|
|
| export async function GET(req: Request) { |
| const admin = requireAdmin(req); |
| if (!admin) { |
| return NextResponse.json({ error: 'Admin access required' }, { status: 403 }); |
| } |
|
|
| const url = new URL(req.url); |
| const userId = url.searchParams.get('userId') || undefined; |
| const actionRaw = url.searchParams.get('action'); |
| const since = url.searchParams.get('since') || undefined; |
| const limit = Math.min( |
| 500, |
| Math.max(1, parseInt(url.searchParams.get('limit') || '50', 10)), |
| ); |
| const offset = Math.max(0, parseInt(url.searchParams.get('offset') || '0', 10)); |
|
|
| |
| let action: AuditAction | undefined; |
| if (actionRaw) { |
| if (!ALLOWED_ACTIONS.has(actionRaw as AuditAction)) { |
| return NextResponse.json( |
| { error: `Unknown action: ${actionRaw}` }, |
| { status: 400 }, |
| ); |
| } |
| action = actionRaw as AuditAction; |
| } |
|
|
| |
| |
| const entries = queryAudit({ userId, action, since, limit: limit + 1, offset }); |
| const hasMore = entries.length > limit; |
| if (hasMore) entries.pop(); |
|
|
| return NextResponse.json({ entries, limit, offset, hasMore }); |
| } |
|
|