36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
import { errorResponse, requireSameOrigin, readJson } from "@/lib/security/http";
|
|
import { limitRequest } from "@/lib/security/rate-limit";
|
|
import { requireAdmin } from "@/lib/auth/server";
|
|
import { createPendingMedia } from "@/lib/media/repository";
|
|
import { mediaUploadSchema } from "@/lib/media/validation";
|
|
|
|
export async function POST(request: Request) {
|
|
try {
|
|
requireSameOrigin(request);
|
|
const admin = await requireAdmin();
|
|
await limitRequest("media", admin.user.id, 20);
|
|
const input = await readJson(request);
|
|
const parsed = mediaUploadSchema.safeParse(input);
|
|
if (!parsed.success) {
|
|
return Response.json(
|
|
{ error: "invalid-media", issues: parsed.error.issues.map((issue) => issue.message) },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
try {
|
|
const upload = await createPendingMedia(parsed.data, admin.user.id);
|
|
return Response.json({
|
|
mediaId: upload.id,
|
|
uploadUrl: upload.uploadUrl,
|
|
method: "PUT",
|
|
headers: { "Content-Type": parsed.data.mimeType },
|
|
expiresIn: upload.expiresIn,
|
|
});
|
|
} catch {
|
|
return Response.json({ error: "storage-unavailable" }, { status: 503 });
|
|
}
|
|
} catch (cause) {
|
|
return errorResponse(cause);
|
|
}
|
|
}
|