61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
import { auth } from "~/lib/auth.server";
|
|
import { uploadSportIcon } from "~/lib/cloudinary.server";
|
|
import { logger } from "~/lib/logger";
|
|
import { isUserAdmin } from "~/models/user";
|
|
import type { Route } from "./+types/api.upload-sport-icon";
|
|
|
|
const MAX_UPLOAD_BYTES = 1024 * 1024;
|
|
|
|
function isSvgFile(file: File): boolean {
|
|
return file.type === "image/svg+xml" || file.name.toLowerCase().endsWith(".svg");
|
|
}
|
|
|
|
function looksLikeSvg(buffer: Buffer): boolean {
|
|
return buffer.toString("utf8", 0, Math.min(buffer.length, 1024)).includes("<svg");
|
|
}
|
|
|
|
export async function action({ request }: Route.ActionArgs) {
|
|
const session = await auth.api.getSession({ headers: request.headers });
|
|
const userId = session?.user.id ?? null;
|
|
|
|
if (!userId) {
|
|
return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
if (!(await isUserAdmin(userId))) {
|
|
return Response.json({ error: "Forbidden" }, { status: 403 });
|
|
}
|
|
|
|
const formData = await request.formData();
|
|
const file = formData.get("file");
|
|
const slug = formData.get("slug");
|
|
|
|
if (!(file instanceof File)) {
|
|
return Response.json({ error: "SVG file is required" }, { status: 400 });
|
|
}
|
|
|
|
if (!isSvgFile(file)) {
|
|
return Response.json({ error: "Icon must be an SVG file" }, { status: 400 });
|
|
}
|
|
|
|
if (file.size > MAX_UPLOAD_BYTES) {
|
|
return Response.json({ error: "Icon must be under 1 MB" }, { status: 400 });
|
|
}
|
|
|
|
try {
|
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
if (!looksLikeSvg(buffer)) {
|
|
return Response.json({ error: "Icon must be a valid SVG file" }, { status: 400 });
|
|
}
|
|
|
|
const result = await uploadSportIcon({
|
|
buffer,
|
|
slug: typeof slug === "string" ? slug : null,
|
|
});
|
|
|
|
return Response.json({ iconUrl: result.secure_url });
|
|
} catch (error) {
|
|
logger.error("Sport icon upload failed:", error);
|
|
return Response.json({ error: "Upload failed" }, { status: 500 });
|
|
}
|
|
}
|