import { json, requireAdmin } from "../../../../_lib/auth"; import { addUpload, isJpeg, removeUpload } from "../../../../_lib/photos"; export const dynamic = "force-dynamic"; /** * The admin page resizes photos in the browser (max 1920px JPEG plus a 64px thumbnail) * before sending them, so the server only validates and stores. */ export async function POST(request: Request) { const denied = await requireAdmin(request, { mutating: true }); if (denied) return denied; let form: FormData; try { form = await request.formData(); } catch { return json({ error: "Expected a photo upload." }, 400); } const photo = form.get("photo"); const thumb = form.get("thumb"); if (!(photo instanceof Blob) || !(thumb instanceof Blob)) return json({ error: "Missing photo." }, 400); if (photo.size > 8 * 1024 * 1024 || thumb.size > 256 * 1024) return json({ error: "Photo is too large." }, 413); const photoBytes = new Uint8Array(await photo.arrayBuffer()); const thumbBytes = new Uint8Array(await thumb.arrayBuffer()); if (!isJpeg(photoBytes) || !isJpeg(thumbBytes)) return json({ error: "Photos must be JPEG." }, 415); const takenAt = Number(form.get("takenAt")); try { const result = await addUpload(photoBytes, thumbBytes, { takenAt: Number.isFinite(takenAt) && takenAt > 0 ? takenAt : null, width: Math.max(0, Math.round(Number(form.get("width")) || 0)), height: Math.max(0, Math.round(Number(form.get("height")) || 0)), }); return json({ ok: true, ...result }); } catch (error) { return json({ error: error instanceof Error ? error.message : "Upload failed." }, 400); } } export async function DELETE(request: Request) { const denied = await requireAdmin(request, { mutating: true }); if (denied) return denied; const key = new URL(request.url).searchParams.get("key") || ""; return (await removeUpload(key)) ? json({ ok: true }) : json({ error: "Not found." }, 404); }