From 3e4c6241f649381015deb4d98ea181f4c416bbd6 Mon Sep 17 00:00:00 2001 From: makearmy Date: Tue, 30 Sep 2025 09:29:44 -0400 Subject: [PATCH] password auth fix for accounts --- app/api/account/password/route.ts | 60 +++++++++++++++++-------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/app/api/account/password/route.ts b/app/api/account/password/route.ts index f8ffdde8..5f515bdf 100644 --- a/app/api/account/password/route.ts +++ b/app/api/account/password/route.ts @@ -1,40 +1,46 @@ // app/api/account/password/route.ts -export const runtime = "nodejs"; - 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 }); -function bad(msg: string, code = 400) { - return NextResponse.json({ error: msg }, { status: code }); -} +async function handle(req: Request) { + const bearer = requireBearer(req); -export async function POST(req: Request) { - try { - const bearer = requireBearer(req); - const body = await req.json().catch(() => ({})); + const body = await req.json().catch(() => ({})); + const current = + String(body?.current ?? body?.current_password ?? "").trim(); + const next = + String(body?.next ?? body?.new_password ?? "").trim(); - // accept various shapes: {next}, {new_password}, {password} - const nextPwd = - String(body?.next ?? body?.new_password ?? body?.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"); - if (nextPwd.length < 8) return bad("Password must be at least 8 characters"); + const res = await fetch(`${API}/users/me`, { + method: "PATCH", + headers: { + Authorization: bearer, + "Content-Type": "application/json", + }, + body: JSON.stringify({ password: next, old_password: current }), + }); - const res = await fetch(`${API}/users/me`, { - method: "PATCH", - headers: { Authorization: bearer, "Content-Type": "application/json" }, - body: JSON.stringify({ password: nextPwd }), - }); + const j = await res.json().catch(() => ({})); - const j = await res.json().catch(() => ({})); - if (!res.ok) { - return bad(j?.errors?.[0]?.message || "Password update failed", res.status); - } - - // tell the client to re-auth so their token reflects the password change - return NextResponse.json({ ok: true, requireReauth: true }); - } catch (e: any) { - return bad(e?.message || "Unexpected error", e?.status || 500); + if (!res.ok) { + const reason = j?.errors?.[0]?.message || "Password change failed"; + const friendly = /invalid|credential|old_password|incorrect/i.test(reason) + ? "Current password is incorrect" + : reason; + // Propagate upstream status (401/403/400…) so the UI can react. + return NextResponse.json({ error: friendly }, { 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); }