import { NextResponse } from "next/server"; import { z } from "zod"; import { getSessionUser } from "@/lib/session"; import { getHumanUserDetail, updateHumanUserProfile, } from "@/lib/zitadel"; /** * GET /api/settings/profile — read the caller's ZITADEL profile. * Returns first/last/display name and email. Used by the settings * page server component to populate the form. * * PUT /api/settings/profile — update first + last name. Email is * NOT mutable here — changing email needs verification flow that * ZITADEL's own self-service UI already provides; we don't * duplicate that. * * Authorization: any authenticated user can edit their own profile. * The PAT (ZITADEL_SA_PAT) is used to call the ZITADEL v2 user * service, but only against the caller's own userId. There is no * userId field on the request — it's always derived from the * session, so the route can't be abused to edit other users. */ const updateSchema = z.object({ firstName: z.string().trim().min(1).max(100), lastName: z.string().trim().min(1).max(100), }); export async function GET() { const user = await getSessionUser(); if (!user) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } try { const profile = await getHumanUserDetail(user.id); return NextResponse.json({ profile }); } catch (e: any) { // Surface ZITADEL-side failures (e.g. user not found, PAT expired) // as 502 — the portal couldn't reach its identity provider, which // is operationally different from a 4xx on the caller's input. console.error("getHumanUserDetail failed:", e); return NextResponse.json( { error: "Could not load profile from identity provider" }, { status: 502 } ); } } export async function PUT(request: Request) { const user = await getSessionUser(); if (!user) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const body = await request.json().catch(() => ({})); const parsed = updateSchema.safeParse(body); if (!parsed.success) { return NextResponse.json( { error: "Invalid request", details: parsed.error.flatten() }, { status: 400 } ); } try { const result = await updateHumanUserProfile({ userId: user.id, givenName: parsed.data.firstName, familyName: parsed.data.lastName, }); return NextResponse.json({ displayName: result.displayName, changeDate: result.changeDate, }); } catch (e: any) { console.error("updateHumanUserProfile failed:", e); return NextResponse.json( { error: "Could not update profile in identity provider" }, { status: 502 } ); } }