import { getAuthRuntimeConfig, safeNextPath } from "@/lib/auth/config"; import { jsonError, jsonOk, readJsonBody } from "@/lib/server/api"; import { authenticatePlatformUser } from "@/lib/server/account-store"; import { checkIpLoginRateLimit, clearIpLoginRateLimit, clientIpFromRequest, createPlatformSession, setPlatformSessionCookie } from "@/lib/server/auth/local"; export const runtime = "nodejs"; export const dynamic = "force-dynamic"; export async function POST(request: Request) { const ip = clientIpFromRequest(request); try { const config = getAuthRuntimeConfig(); if (!config.configured || !config.sessionSecret) { throw Object.assign(new Error(`账号认证配置不完整:${config.missing.join(", ") || "ZHINIAN_AUTH_SESSION_SECRET"}`), { status: 503 }); } checkIpLoginRateLimit(ip); const body = await readJsonBody>(request); const phone = stringValue(body.phone) || stringValue(body.username); const password = stringValue(body.password); if (!phone || !password) throw Object.assign(new Error("手机号和密码不能为空。"), { status: 400 }); const user = await authenticatePlatformUser(phone, password); clearIpLoginRateLimit(ip); const session = await createPlatformSession(user); const response = jsonOk({ ok: true, redirectTo: safeNextPath(stringValue(body.next)), user: session.user, authMode: session.authMode }); await setPlatformSessionCookie(response, request.url, session); return response; } catch (error) { return jsonError(error, 401, { request, source: "api.auth.password", logClientErrors: false }); } } function stringValue(value: unknown): string | undefined { return typeof value === "string" && value.trim() ? value.trim() : undefined; }