Phase 19: Local Auth (No-OIDC Mode) #23
@@ -168,10 +168,14 @@ export async function fetchChangePassword(body: {
|
||||
* POST /api/admin/members — create a new local member account (Phase 19, Surface 11A).
|
||||
* Admin-only; server enforces requireAdmin.
|
||||
*
|
||||
* Request contract: the server's createMemberSchema requires
|
||||
* { displayName, username, initialPassword }
|
||||
* (see apps/api/src/routes/admin.ts). The caller-facing `password` field is mapped to
|
||||
* `initialPassword` here so the request validates server-side.
|
||||
*
|
||||
* Status codes:
|
||||
* 409 → username already taken
|
||||
* 422 → validation failure (short password / mismatch)
|
||||
* other non-ok → generic error
|
||||
* 409 → username already taken (throws Error with message 'conflict')
|
||||
* other non-ok → generic error (throws Error('server'))
|
||||
*/
|
||||
export async function fetchCreateMember(body: {
|
||||
displayName: string;
|
||||
@@ -183,10 +187,19 @@ export async function fetchCreateMember(body: {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
redirect: 'manual',
|
||||
body: JSON.stringify(body),
|
||||
// CR-02: the server expects `initialPassword`, not `password`. Send the field it
|
||||
// validates against — otherwise Zod rejects every create with a generic 400.
|
||||
body: JSON.stringify({
|
||||
displayName: body.displayName,
|
||||
username: body.username,
|
||||
initialPassword: body.password,
|
||||
}),
|
||||
});
|
||||
|
||||
if (res.type === 'opaqueredirect' || res.status === 401) throw new SessionExpiredError();
|
||||
// 409 → username conflict. The server returns { error: 'Username already in use' } (no
|
||||
// `code` field), so map the status to the 'conflict' sentinel the AdminPage handler expects.
|
||||
if (res.status === 409) throw new Error('conflict');
|
||||
if (!res.ok) {
|
||||
const detail = (await res.json().catch(() => ({}))) as { code?: string };
|
||||
throw new Error(detail.code ?? 'server');
|
||||
|
||||
Reference in New Issue
Block a user