makearmy-app/app/api/account/password/route.ts
2025-09-30 20:55:19 -04:00

81 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// app/api/account/password/route.ts
import { NextResponse } from "next/server";
import { requireBearer } from "@/app/api/_lib/auth";
import { loginDirectus } from "@/lib/directus";
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) Load the current user to get email + provider
const meRes = await fetch(`${API}/users/me?fields=id,email,provider`, {
headers: { Authorization: `Bearer ${bearer}`, Accept: "application/json" },
cache: "no-store",
});
const me = await meRes.json().catch(() => ({}));
if (!meRes.ok) {
return NextResponse.json(
{ error: "Could not verify user", debug: me?.errors?.[0]?.message || meRes.statusText },
{ status: meRes.status }
);
}
const email: string | undefined = me?.data?.email ?? me?.email;
const provider: string = me?.data?.provider ?? me?.provider ?? "local";
if (!email) {
return NextResponse.json(
{ error: "User email not available", debug: "users/me returned no email" },
{ status: 400 }
);
}
if (provider !== "local") {
return NextResponse.json(
{ error: "Password managed by external provider", debug: `provider=${provider}` },
{ status: 400 }
);
}
// 2) Verify the CURRENT password by logging in to Directus
const auth = await loginDirectus(email, current).catch(() => null);
const access = auth?.access_token ?? auth?.data?.access_token;
if (!access) {
// Weve confirmed the “current” really doesnt match
return NextResponse.json({ error: "Current password is incorrect" }, { status: 401 });
}
// 3) Update password using ONLY the 'password' field (avoid non-existent keys)
const patchRes = await fetch(`${API}/users/me`, {
method: "PATCH",
headers: {
Authorization: `Bearer ${bearer}`,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({ password: next }),
});
const j = await patchRes.json().catch(() => ({}));
if (!patchRes.ok) {
const reason =
j?.errors?.[0]?.message || j?.error || (typeof j === "string" ? j : "") || "Password change failed";
return NextResponse.json({ error: reason }, { status: patchRes.status });
}
return NextResponse.json({ ok: true });
}
export async function POST(req: Request) { return handle(req); }
export async function PATCH(req: Request) { return handle(req); }