fix: save profiles through account route
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { isAdminEmail } from "@/lib/supabase/admin";
|
||||
import { createAdminSupabaseClient, isAdminEmail } from "@/lib/supabase/admin";
|
||||
import {
|
||||
isSupabaseConfigurationError,
|
||||
} from "@/lib/supabase/config";
|
||||
@@ -7,6 +7,27 @@ import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
type ProfilePatchPayload = {
|
||||
name?: unknown;
|
||||
birth_date?: unknown;
|
||||
birth_time?: unknown;
|
||||
country_code?: unknown;
|
||||
province_code?: unknown;
|
||||
city_code?: unknown;
|
||||
district_code?: unknown;
|
||||
latitude?: unknown;
|
||||
longitude?: unknown;
|
||||
timezone_offset?: unknown;
|
||||
};
|
||||
|
||||
function nullableString(value: unknown) {
|
||||
return typeof value === "string" && value.trim() ? value.trim() : null;
|
||||
}
|
||||
|
||||
function nullableNumber(value: unknown) {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const supabase = await createServerSupabaseClient();
|
||||
@@ -38,3 +59,50 @@ export async function GET() {
|
||||
return NextResponse.json({ error: "账户服务暂时不可用" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PATCH(request: Request) {
|
||||
try {
|
||||
const supabase = await createServerSupabaseClient();
|
||||
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
||||
|
||||
if (authError || !user) {
|
||||
return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
const payload = await request.json().catch(() => null) as ProfilePatchPayload | null;
|
||||
if (!payload || typeof payload !== "object") {
|
||||
return NextResponse.json({ error: "账户资料格式不正确" }, { status: 400 });
|
||||
}
|
||||
|
||||
const admin = createAdminSupabaseClient();
|
||||
const { data, error } = await admin
|
||||
.from("profiles")
|
||||
.upsert({
|
||||
id: user.id,
|
||||
name: nullableString(payload.name),
|
||||
birth_date: nullableString(payload.birth_date),
|
||||
birth_time: nullableString(payload.birth_time),
|
||||
country_code: nullableString(payload.country_code),
|
||||
province_code: nullableString(payload.province_code),
|
||||
city_code: nullableString(payload.city_code),
|
||||
district_code: nullableString(payload.district_code),
|
||||
latitude: nullableNumber(payload.latitude),
|
||||
longitude: nullableNumber(payload.longitude),
|
||||
timezone_offset: nullableNumber(payload.timezone_offset),
|
||||
updated_at: new Date().toISOString(),
|
||||
}, { onConflict: "id" })
|
||||
.select("id")
|
||||
.single();
|
||||
|
||||
if (error || !data) {
|
||||
return NextResponse.json({ error: "暂时无法保存账户资料" }, { status: 500 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (error) {
|
||||
if (isSupabaseConfigurationError(error)) {
|
||||
return NextResponse.json({ error: "Supabase 尚未配置", code: "SUPABASE_NOT_CONFIGURED" }, { status: 503 });
|
||||
}
|
||||
return NextResponse.json({ error: "账户服务暂时不可用" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1320,10 +1320,10 @@ export default function Home() {
|
||||
if (!account) throw new Error("账户尚未加载完成");
|
||||
if (process.env.NODE_ENV === "development" && uiPreview.current) return;
|
||||
const birthPlace = selectedBirthPlace(nextProfile);
|
||||
const { data, error } = await createBrowserSupabaseClient()
|
||||
.from("profiles")
|
||||
.upsert({
|
||||
id: account.user.id,
|
||||
const response = await fetch("/api/account", {
|
||||
method: "PATCH",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
name: nextProfile.name.trim() || null,
|
||||
birth_date: nextProfile.date || null,
|
||||
birth_time: nextProfile.time || null,
|
||||
@@ -1334,12 +1334,12 @@ export default function Home() {
|
||||
latitude: birthPlace?.lat ?? null,
|
||||
longitude: birthPlace?.lon ?? null,
|
||||
timezone_offset: birthPlace?.tz ?? null,
|
||||
updated_at: new Date().toISOString(),
|
||||
}, { onConflict: "id" })
|
||||
.select("id")
|
||||
.maybeSingle();
|
||||
if (error) throw error;
|
||||
if (!data) throw new Error("账户档案不存在,请重新登录后再试。");
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch(() => null) as { error?: string } | null;
|
||||
throw new Error(payload?.error || "账户资料暂时无法保存。");
|
||||
}
|
||||
await saveCloudChartProfile({ ...buildSelfChartRecord(nextProfile), updatedAt: timestamp() }).catch(() => null);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,5 +4,11 @@ import test from "node:test";
|
||||
|
||||
test("upserts a missing profile when saving account details", () => {
|
||||
const source = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8");
|
||||
assert.match(source, /fetch\("\/api\/account",\s*\{\s*method:\s*"PATCH"/s);
|
||||
});
|
||||
|
||||
test("account route upserts profiles with the server admin client", () => {
|
||||
const source = readFileSync(new URL("../src/app/api/account/route.ts", import.meta.url), "utf8");
|
||||
assert.match(source, /createAdminSupabaseClient\(\)/);
|
||||
assert.match(source, /\.from\("profiles"\)\s*\.upsert\(/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user