149 lines
4.3 KiB
TypeScript
149 lines
4.3 KiB
TypeScript
import { createFileRoute } from "@tanstack/react-router";
|
|
import { superTokensRequestMiddleware } from "@/utils/supertokens";
|
|
import { pbAdmin } from "@/lib/pocketbase/client";
|
|
import { logger } from "@/lib/logger";
|
|
import { z } from "zod";
|
|
|
|
const uploadSchema = z.object({
|
|
teamId: z.string().min(1, "Team ID is required"),
|
|
});
|
|
|
|
export const Route = createFileRoute("/api/teams/upload-logo")({
|
|
server: {
|
|
middleware: [superTokensRequestMiddleware],
|
|
handlers: {
|
|
POST: async ({ request, context }) => {
|
|
try {
|
|
const userId = context.userAuthId;
|
|
const isAdmin = context.roles.includes("Admin");
|
|
|
|
if (!userId) return new Response("Unauthenticated", { status: 401 });
|
|
|
|
const formData = await request.formData();
|
|
const teamId = formData.get("teamId") as string;
|
|
const logoFile = formData.get("logo") as File;
|
|
|
|
const validationResult = uploadSchema.safeParse({ teamId });
|
|
if (!validationResult.success) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
error: "Invalid input",
|
|
details: validationResult.error.issues,
|
|
}),
|
|
{
|
|
status: 400,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}
|
|
|
|
if (!logoFile || logoFile.size === 0) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
error: "Logo file is required",
|
|
}),
|
|
{
|
|
status: 400,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}
|
|
|
|
const allowedTypes = [
|
|
"image/jpeg",
|
|
"image/jpg",
|
|
"image/png",
|
|
"image/gif",
|
|
];
|
|
if (!allowedTypes.includes(logoFile.type)) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
error: "Invalid file type. Only JPEG, PNG and GIF are allowed.",
|
|
}),
|
|
{
|
|
status: 400,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}
|
|
|
|
const maxSize = 10 * 1024 * 1024;
|
|
if (logoFile.size > maxSize) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
error: "File too large. Maximum size is 10MB.",
|
|
}),
|
|
{
|
|
status: 400,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}
|
|
|
|
const team = await pbAdmin.getTeam(teamId);
|
|
if (!team) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
error: "Team not found",
|
|
}),
|
|
{
|
|
status: 404,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}
|
|
|
|
const user = await pbAdmin.getPlayerByAuthId(userId);
|
|
if (!team.players.map((p) => p.id).includes(user?.id!) && !isAdmin)
|
|
return new Response("Unauthorized", { status: 403 });
|
|
|
|
logger.info("Uploading team logo", {
|
|
teamId,
|
|
fileName: logoFile.name,
|
|
fileSize: logoFile.size,
|
|
userId,
|
|
});
|
|
|
|
const pbFormData = new FormData();
|
|
pbFormData.append("logo", logoFile);
|
|
|
|
const updatedTeam = await pbAdmin.updateTeam(
|
|
teamId,
|
|
pbFormData as any
|
|
);
|
|
|
|
logger.info("Team logo uploaded successfully", {
|
|
teamId,
|
|
logo: updatedTeam.logo,
|
|
});
|
|
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: true,
|
|
team: updatedTeam,
|
|
message: "Logo uploaded successfully",
|
|
}),
|
|
{
|
|
status: 200,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
} catch (error: any) {
|
|
logger.error("Error uploading team logo:", error);
|
|
|
|
return new Response(
|
|
JSON.stringify({
|
|
error: "Failed to upload logo",
|
|
message: error.message || "Unknown error occurred",
|
|
}),
|
|
{
|
|
status: 500,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}
|
|
},
|
|
},
|
|
},
|
|
});
|