Secure profile photo uploads and trust configured production origin
All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 8m53s

This commit is contained in:
2026-10-15 14:00:46 +05:00
parent 07cd0993a0
commit 930e00a736
5 changed files with 198 additions and 71 deletions

View File

@@ -4,13 +4,11 @@ import { useI18n } from "@/components/I18nProvider";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { UserRound, LockKeyhole, Mail } from "lucide-react";
import { createBrowserClient } from "@supabase/ssr";
import { api } from "./StartGame";
import { PasswordForm } from "./PasswordForm";
import { displayNameSchema } from "@/shared/account";
import {
defaultGlowColor,
profileAvatarBucket,
profileAvatarMaxBytes,
profileAvatarMimeTypes,
type ProfileAppearance,
@@ -68,37 +66,18 @@ export function AccountSettings({
setPhotoError("Choose a JPG, PNG or WebP image.");
return;
}
const extension =
file.type === "image/jpeg"
? "jpg"
: file.type === "image/png"
? "png"
: "webp";
const path = `${accountId}/${crypto.randomUUID()}.${extension}`;
const client = createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
);
setPhotoBusy(true);
let uploaded = false;
try {
const { error: uploadError } = await client.storage
.from(profileAvatarBucket)
.upload(path, file, {
cacheControl: "31536000",
contentType: file.type,
upsert: false,
});
if (uploadError)
throw new Error("Could not upload your profile photo. Please try again.");
uploaded = true;
await api("profile", { avatarPath: path }, "PATCH");
setPhotoPath(path);
const form = new FormData();
form.append("photo", file);
const result = await api<{ profile: { avatar_path: string } }>(
"profile/avatar",
form,
);
setPhotoPath(result.profile.avatar_path);
setPhotoSaved(true);
router.refresh();
} catch (error) {
if (uploaded)
await client.storage.from(profileAvatarBucket).remove([path]);
setPhotoError((error as Error).message);
} finally {
setPhotoBusy(false);