← back to Norma
app/api/audit/route.ts
61 lines
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';
/**
* GET /api/audit
* List audit events with optional filters.
* Query params: ?event_type=, ?entity_type=, ?entity_id=, ?limit= (default 50)
* Ordered by created_at DESC.
*/
export async function GET(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const { searchParams } = new URL(request.url);
const eventType = searchParams.get('event_type');
const entityType = searchParams.get('entity_type');
const entityId = searchParams.get('entity_id');
const limitParam = searchParams.get('limit');
const limit = Math.min(Math.max(parseInt(limitParam || '50', 10) || 50, 1), 500);
const conditions: string[] = [];
const values: unknown[] = [];
let paramIndex = 1;
if (eventType) {
conditions.push(`event_type = $${paramIndex}`);
values.push(eventType);
paramIndex++;
}
if (entityType) {
conditions.push(`entity_type = $${paramIndex}`);
values.push(entityType);
paramIndex++;
}
if (entityId) {
conditions.push(`entity_id = $${paramIndex}`);
values.push(entityId);
paramIndex++;
}
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
values.push(limit);
const result = await query(
`SELECT * FROM audit_events ${whereClause}
ORDER BY created_at DESC
LIMIT $${paramIndex}`,
values
);
return NextResponse.json({ events: result.rows });
} catch (err) {
console.error('[api/audit] GET error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to fetch audit events' }, { status: 500 });
}
}