import { serverSupabaseServiceRole } from "../../utils/useSupabase"; import { updateProfile } from "../../db/profile"; /** * POST /api/avatar/upload * Body: { dataUrl: string } (base64 JPEG/PNG data URL) */ export default defineEventHandler(async (event) => { const user = await requireUser(event); const { dataUrl } = (await readBody(event)) as { dataUrl: string }; if (!dataUrl?.startsWith("data:image/")) { throw createError({ statusCode: 400, message: "Ungültige Bilddaten" }); } const match = dataUrl.match(/^data:(image\/\w+);base64,(.+)$/); if (!match) throw createError({ statusCode: 400, message: "Ungültiges Bildformat" }); const contentType = match[1]; const ext = contentType === "image/png" ? "png" : "jpg"; const base64 = match[2]; const binaryStr = atob(base64); const bytes = new Uint8Array(binaryStr.length); for (let i = 0; i < binaryStr.length; i++) { bytes[i] = binaryStr.charCodeAt(i); } const blob = new Blob([bytes], { type: contentType }); const supabase = serverSupabaseServiceRole(event); const path = `avatars/${user.id}.${ext}`; const { error: uploadError } = await supabase.storage .from("rebreak-avatars") .upload(path, blob, { contentType, upsert: true }); if (uploadError) { console.error("[avatar/upload] Storage error:", uploadError); throw createError({ statusCode: 500, message: uploadError.message }); } const { data: urlData } = supabase.storage .from("rebreak-avatars") .getPublicUrl(path); const publicUrl = urlData.publicUrl + `?t=${Date.now()}`; // In beide schreiben: profiles (für Prisma include) + user_metadata (für me.get) await Promise.all([ updateProfile(user.id, { avatar: publicUrl }), supabase.auth.admin.updateUserById(user.id, { user_metadata: { avatar: publicUrl }, }), ]); return { url: publicUrl }; });