import { NextRequest, NextResponse } from "next/server"; import { getPocketBaseConfig, SITE_ID } from "@/config/services.config"; async function getAdminToken(): Promise { const email = process.env.POCKETBASE_EMAIL; const password = process.env.POCKETBASE_PASSWORD; if (!email || !password) return null; const pb = getPocketBaseConfig(); const res = await fetch(`${pb.url}/api/admins/auth-with-password`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ identity: email, password }), }); if (!res.ok) return null; const data = await res.json(); return data?.token ?? null; } /** 将匿名 user_id 的支付记录关联到新创建的 PB 用户 */ async function linkPaymentsToUser( adminToken: string, fromUserId: string, toUserId: string ): Promise { const pb = getPocketBaseConfig(); const filter = `user_id = "${fromUserId}"`; const res = await fetch( `${pb.url}/api/collections/payments/records?filter=${encodeURIComponent(filter)}&perPage=500`, { headers: { Authorization: `Bearer ${adminToken}` } } ); if (!res.ok) return; const data = await res.json(); const items = data?.items ?? []; for (const item of items) { await fetch(`${pb.url}/api/collections/payments/records/${item.id}`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: `Bearer ${adminToken}`, }, body: JSON.stringify({ user_id: toUserId }), }); } } async function linkSiteVipToUser( adminToken: string, fromUserId: string, toUserId: string ): Promise { const pb = getPocketBaseConfig(); const filter = `user_id = "${fromUserId}" && site_id = "${SITE_ID}"`; const res = await fetch( `${pb.url}/api/collections/site_vip/records?filter=${encodeURIComponent(filter)}&perPage=500`, { headers: { Authorization: `Bearer ${adminToken}` } } ); if (!res.ok) return; const data = await res.json(); const items = data?.items ?? []; for (const item of items) { await fetch(`${pb.url}/api/collections/site_vip/records/${item.id}`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: `Bearer ${adminToken}`, }, body: JSON.stringify({ user_id: toUserId }), }); } } export async function POST(request: NextRequest) { const body = await request.json().catch(() => ({})); const email = String(body?.email ?? "").trim(); const password = String(body?.password ?? "").trim(); const anonymousUserId = String(body?.anonymousUserId ?? "").trim(); if (!email || !password) { return NextResponse.json({ ok: false, error: "请填写邮箱和密码" }, { status: 400 }); } if (!anonymousUserId || !anonymousUserId.startsWith("user")) { return NextResponse.json({ ok: false, error: "无效的匿名用户ID" }, { status: 400 }); } if (password.length < 8) { return NextResponse.json({ ok: false, error: "密码至少 8 位" }, { status: 400 }); } const pb = getPocketBaseConfig(); // 1. 尝试注册,若已存在则登录 let token: string; let record: { id: string; email?: string }; try { const registerRes = await fetch(`${pb.url}/api/collections/users/records`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password, passwordConfirm: password }), }); if (registerRes.ok) { const regData = await registerRes.json(); 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 }), }); if (!loginRes.ok) throw new Error("登录失败"); const loginData = await loginRes.json(); token = loginData.token; record = loginData.record; } else { 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 }), }); if (!loginRes.ok) { const err = await loginRes.json().catch(() => ({})); return NextResponse.json( { ok: false, error: err?.message || "邮箱或密码错误" }, { status: 401 } ); } const loginData = await loginRes.json(); token = loginData.token; record = loginData.record; } } catch (e) { return NextResponse.json( { ok: false, error: e instanceof Error ? e.message : "注册/登录失败" }, { status: 500 } ); } const newUserId = record.id; // 2. 用管理员 token 将 payments、site_vip 的 user_id 从匿名改为新用户 const adminToken = await getAdminToken(); if (adminToken) { await linkPaymentsToUser(adminToken, anonymousUserId, newUserId); await linkSiteVipToUser(adminToken, anonymousUserId, newUserId); } return NextResponse.json({ ok: true, token, record: { id: record.id, email: record.email }, }); }