Initial push

This commit is contained in:
2026-03-08 15:49:34 +01:00
parent 8da12bb7d1
commit 47127f276d
101 changed files with 13844 additions and 8 deletions

48
app/api/audit/route.ts Normal file
View File

@@ -0,0 +1,48 @@
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 });
}