49 lines
1.9 KiB
TypeScript
49 lines
1.9 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { auth } from "@/lib/auth";
|
|
import { db } from "@/lib/db";
|
|
import { auditLogs, users } from "@/lib/db/schema";
|
|
import { checkRateLimit, getClientIp } from "@/lib/security/rateLimit";
|
|
import { desc, eq, like, and, gte, lte } from "drizzle-orm";
|
|
|
|
export async function GET(req: NextRequest) {
|
|
const session = await auth.api.getSession({ headers: req.headers });
|
|
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
if (!["superadmin", "admin"].includes(session.user.role ?? "")) {
|
|
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
|
}
|
|
|
|
const ip = getClientIp(req);
|
|
const { allowed } = checkRateLimit(ip);
|
|
if (!allowed) return NextResponse.json({ error: "Too many requests" }, { status: 429 });
|
|
|
|
const { searchParams } = new URL(req.url);
|
|
const page = Math.max(1, parseInt(searchParams.get("page") ?? "1"));
|
|
const limit = Math.min(100, parseInt(searchParams.get("limit") ?? "50"));
|
|
const offset = (page - 1) * limit;
|
|
const userId = searchParams.get("userId");
|
|
const action = searchParams.get("action");
|
|
const from = searchParams.get("from");
|
|
const to = searchParams.get("to");
|
|
|
|
const conditions = [];
|
|
if (userId) conditions.push(eq(auditLogs.userId, userId));
|
|
if (action) conditions.push(like(auditLogs.action, `${action}%`));
|
|
if (from) conditions.push(gte(auditLogs.createdAt, parseInt(from)));
|
|
if (to) conditions.push(lte(auditLogs.createdAt, parseInt(to)));
|
|
|
|
const logs = await db
|
|
.select({
|
|
log: auditLogs,
|
|
userName: users.name,
|
|
userEmail: users.email,
|
|
})
|
|
.from(auditLogs)
|
|
.leftJoin(users, eq(auditLogs.userId, users.id))
|
|
.where(conditions.length ? and(...conditions) : undefined)
|
|
.orderBy(desc(auditLogs.createdAt))
|
|
.limit(limit)
|
|
.offset(offset);
|
|
|
|
return NextResponse.json({ logs, page, limit });
|
|
}
|