55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { z } from "zod";
|
|
|
|
import { auth } from "@/auth";
|
|
import { UserRole } from "@/generated/prisma/enums";
|
|
import { prisma } from "@/lib/prisma";
|
|
import { presignCarbetUpload } from "@/lib/uploads";
|
|
import { rateLimitRequest } from "@/lib/rate-limit";
|
|
|
|
export const runtime = "nodejs";
|
|
|
|
const schema = z.object({
|
|
carbetId: z.string().min(1),
|
|
mime: z.string().min(3).max(100),
|
|
sizeBytes: z.coerce.number().int().min(1).max(500 * 1024 * 1024),
|
|
});
|
|
|
|
export async function POST(req: Request) {
|
|
const rl = rateLimitRequest(req, "presign", 60_000, 60);
|
|
if (!rl.ok) {
|
|
return NextResponse.json(
|
|
{ error: `Trop de demandes. Réessayez dans ${rl.retryAfter}s.` },
|
|
{ status: 429 },
|
|
);
|
|
}
|
|
const session = await auth();
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
|
|
}
|
|
const parsed = schema.safeParse(await req.json().catch(() => ({})));
|
|
if (!parsed.success) {
|
|
return NextResponse.json({ error: parsed.error.issues[0]?.message ?? "Payload invalide" }, { status: 400 });
|
|
}
|
|
|
|
const carbet = await prisma.carbet.findUnique({
|
|
where: { id: parsed.data.carbetId },
|
|
select: { id: true, ownerId: true },
|
|
});
|
|
if (!carbet) return NextResponse.json({ error: "Carbet introuvable" }, { status: 404 });
|
|
const isOwner = carbet.ownerId === session.user.id;
|
|
const isAdmin = session.user.role === UserRole.ADMIN;
|
|
if (!isOwner && !isAdmin) {
|
|
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
|
}
|
|
|
|
const result = await presignCarbetUpload({
|
|
carbetId: carbet.id,
|
|
mime: parsed.data.mime,
|
|
sizeBytes: parsed.data.sizeBytes,
|
|
});
|
|
if ("error" in result) {
|
|
return NextResponse.json({ error: result.error }, { status: 400 });
|
|
}
|
|
return NextResponse.json(result);
|
|
}
|