// app/api/account/password/route.ts import { NextResponse } from "next/server"; import { requireBearer } from "@/app/api/_lib/auth"; export const runtime = "nodejs"; const API = (process.env.NEXT_PUBLIC_API_BASE_URL || "").replace(/\/$/, ""); const bad = (m: string, c = 400) => NextResponse.json({ error: m }, { status: c }); async function handle(req: Request) { const bearer = requireBearer(req); const body = await req.json().catch(() => ({})); const current = String(body?.current ?? body?.current_password ?? "").trim(); const next = String(body?.next ?? body?.new_password ?? "").trim(); if (!current || !next) return bad("Missing current and/or new password"); if (next.length < 8) return bad("Password must be at least 8 characters"); // 1) Fetch user provider; block with clear message if not local const who = await fetch(`${API}/users/me?fields=id,provider,email`, { headers: { Authorization: `Bearer ${bearer}`, Accept: "application/json" }, cache: "no-store", }); const whoJson = await who.json().catch(() => ({})); if (!who.ok) { return NextResponse.json( { error: "Could not verify user", debug: whoJson?.errors?.[0]?.message || who.statusText }, { status: who.status } ); } const provider = whoJson?.data?.provider ?? whoJson?.provider ?? "local"; if (provider !== "local") { return NextResponse.json( { error: "Password managed by external provider", debug: `provider=${provider}` }, { status: 400 } ); } // 2) Send both "old_password" and "current_password" for cross-version compatibility const payload = { password: next, old_password: current, current_password: current }; const res = await fetch(`${API}/users/me`, { method: "PATCH", headers: { Authorization: `Bearer ${bearer}`, "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify(payload), }); const j = await res.json().catch(() => ({})); if (!res.ok) { const reason = j?.errors?.[0]?.message || j?.error || (typeof j === "string" ? j : "") || "Password change failed"; // Only show the friendly message when it truly looks like a wrong-current-password case. const friendly = res.status === 401 && /old_password|current_password|credential|invalid/i.test(reason) ? "Current password is incorrect" : reason; return NextResponse.json({ error: friendly, debug: reason }, { status: res.status }); } return NextResponse.json({ ok: true }); } export async function POST(req: Request) { return handle(req); } export async function PATCH(req: Request) { return handle(req); }