import { NextRequest, NextResponse } from "next/server"; import { getPocketBaseConfig } from "@/config/services.config"; import { ensureSiteVipForUser, getAdminToken, isAnonymousUserId, upsertVipEmailLink, } from "@/app/api/vip/_helpers"; const DEFAULT_PASSWORD = "12345678"; type PBAuthRecord = { id: string; email?: string; }; async function registerOrLoginUser( email: string, password: string ): Promise<{ token: string; record: PBAuthRecord } | null> { const pb = getPocketBaseConfig(); await fetch(`${pb.url}/api/collections/users/records`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password, passwordConfirm: password, }), cache: "no-store", }).catch(() => null); const loginRes = await fetch( `${pb.url}/api/collections/users/auth-with-password`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ identity: email, password }), cache: "no-store", } ); if (!loginRes.ok) { const error = await loginRes.json().catch(() => ({})); throw new Error(error?.message || "邮箱或密码错误"); } const loginData = await loginRes.json().catch(() => ({})); if (!loginData?.token || !loginData?.record?.id) { throw new Error("邮箱绑定失败"); } return { token: loginData.token, record: loginData.record, }; } export async function POST(request: NextRequest) { const body = await request.json().catch(() => ({})); const email = String(body?.email ?? "").trim().toLowerCase(); const password = String(body?.password ?? "").trim() || DEFAULT_PASSWORD; const anonymousUserId = String(body?.anonymousUserId ?? "").trim(); console.log( "[link-email] request email=%s anonymousUserId=%s", email || "(empty)", anonymousUserId || "(empty)" ); if (!email) { return NextResponse.json( { ok: false, error: "请填写邮箱" }, { status: 400 } ); } if (!isAnonymousUserId(anonymousUserId)) { return NextResponse.json( { ok: false, error: "无效的匿名 user_id" }, { status: 400 } ); } try { const authData = await registerOrLoginUser(email, password); if (!authData) { return NextResponse.json( { ok: false, error: "邮箱绑定失败" }, { status: 500 } ); } const adminToken = await getAdminToken(); if (!adminToken) { return NextResponse.json( { ok: false, error: "PocketBase 管理员认证失败" }, { status: 500 } ); } await ensureSiteVipForUser(adminToken, anonymousUserId, authData.record.id); await upsertVipEmailLink( adminToken, email, authData.record.id, anonymousUserId ); console.log( "[link-email] success email=%s pbUserId=%s anonymousUserId=%s", email, authData.record.id, anonymousUserId ); return NextResponse.json({ ok: true, token: authData.token, record: { id: authData.record.id, email: authData.record.email ?? email, }, }); } catch (error) { console.error("[link-email] failed:", error); const message = error instanceof Error ? error.message : "邮箱绑定失败"; const status = message.includes("密码") || message.includes("邮箱") ? 401 : 500; return NextResponse.json( { ok: false, error: message, }, { status } ); } }