From 3cda22319e69d4c89348b2d36e02c9c85361a5ca Mon Sep 17 00:00:00 2001 From: Alzer Del Zeyger <75466035+Dx-Alz-xD@users.noreply.github.com> Date: Wed, 11 Nov 2026 19:32:01 +0530 Subject: [PATCH] fix(api): reject malformed user-papers and upload requests user-papers passed any json body straight into $in, so a non array or invalid json became a 500. check it is a list of up to 100 subject names with zod. upload now returns 400 when a files entry is text instead of a file, and when more than one pdf is sent instead of quietly dropping the rest --- src/app/api/upload/route.ts | 11 ++++++++++- src/app/api/user-papers/route.ts | 13 ++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/app/api/upload/route.ts b/src/app/api/upload/route.ts index 4cbc6c2..fdc4937 100644 --- a/src/app/api/upload/route.ts +++ b/src/app/api/upload/route.ts @@ -8,11 +8,20 @@ export const runtime = "nodejs"; export async function POST(req: Request) { try { const formData = await req.formData(); - const files = formData.getAll("files").filter(Boolean) as File[]; + const uploads = formData.getAll("files"); + const files = uploads.filter((upload): upload is File => typeof upload !== "string"); const isPdf = formData.get("isPdf") === "true"; const thumbnail = formData.get("thumbnail") as File | null; const campus = formData.get("campus") as string | null; + if (files.length !== uploads.length) { + return failure("every entry in files has to be a file", 400); + } + + if (isPdf && files.length > 1) { + return failure("upload one pdf at a time", 400); + } + if (files.length === 0) { return failure("No files received.", 400); } diff --git a/src/app/api/user-papers/route.ts b/src/app/api/user-papers/route.ts index 8473ff5..0004972 100644 --- a/src/app/api/user-papers/route.ts +++ b/src/app/api/user-papers/route.ts @@ -1,14 +1,21 @@ -import { type StoredSubjects } from "@/interface"; +import { z } from "zod"; import { getPapersBySubjects } from "@/lib/services/paper" import { success, failure } from "@/lib/utils/response"; export const dynamic = "force-dynamic"; +const pinnedSubjects = z.array(z.string().trim().min(1).max(200)).max(100); + export async function POST(req: Request) { try { - const subjects = (await req.json()) as StoredSubjects; + const body: unknown = await req.json().catch(() => null); + const subjects = pinnedSubjects.safeParse(body); + + if (!subjects.success) { + return failure("send a list of up to 100 subject names", 400); + } - const transformedPapers = await getPapersBySubjects(subjects) + const transformedPapers = await getPapersBySubjects(subjects.data) return success(transformedPapers); } catch (error) {