import { type NextRequest } from "next/server"; import { prisma } from "@/lib/prisma"; import { ok, errorResponse, requireRole, ApiError } from "@/lib/api"; import { saveUploadedFile } from "@/lib/files"; import { audit } from "@/lib/audit"; import { clientIp } from "@/lib/request"; export async function GET() { try { await requireRole("admin"); const files = await prisma.fileAsset.findMany({ orderBy: { uploadedAt: "desc" }, take: 200, }); return ok({ files }); } catch (err) { return errorResponse(err); } } export async function POST(req: NextRequest) { try { const user = await requireRole("admin"); const form = await req.formData().catch(() => null); if (!form) throw new ApiError(400, "invalid_form", "Expected multipart/form-data"); const file = form.get("file"); if (!(file instanceof File)) { throw new ApiError(400, "missing_file", "Missing 'file' field"); } const saved = await saveUploadedFile(file, user.id); if (!saved.deduped) { await audit({ actorId: user.id, action: "create", entity: "FileAsset", entityId: saved.id, after: { sha256: saved.sha256, kind: saved.kind, originalName: saved.originalName }, ipAddress: clientIp(req), }); } return ok({ file: saved }, { status: saved.deduped ? 200 : 201 }); } catch (err) { if (err instanceof Error && /Empty file|File too large/.test(err.message)) { return errorResponse(new ApiError(413, "file_rejected", err.message)); } return errorResponse(err); } }