fix(register): reject duplicate usernames before passkey prompt
Friend hit a 500 on /api/register/complete because the Postgres unique constraint fired after the WebAuthn ceremony — they'd already burned a passkey creation by the time the server refused. Pre-check the username in /api/register/start so the join page shows "Username is already taken" before the browser prompts. Also catch the 23505 duplicate-key error in /api/register/complete as a race-condition safety net.
This commit is contained in:
parent
5bb46afe6d
commit
93a63cd42b
|
|
@ -569,6 +569,13 @@ app.post('/api/register/start', async (c) => {
|
|||
return c.json({ error: 'Username required' }, 400);
|
||||
}
|
||||
|
||||
// Reject duplicates up front so the user isn't prompted to create a passkey
|
||||
// that the /complete step would then reject with a unique-constraint crash.
|
||||
const existing = await getUserByUsername(username);
|
||||
if (existing) {
|
||||
return c.json({ error: `Username "${username}" is already taken — pick a different one.` }, 409);
|
||||
}
|
||||
|
||||
// Generate challenge
|
||||
const challenge = Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString('base64url');
|
||||
|
||||
|
|
@ -658,7 +665,14 @@ app.post('/api/register/complete', async (c) => {
|
|||
const did = (clientDid && typeof clientDid === 'string' && clientDid.startsWith('did:key:z'))
|
||||
? clientDid
|
||||
: `did:key:${userId.slice(0, 32)}`;
|
||||
await createUser(userId, username, username, did);
|
||||
try {
|
||||
await createUser(userId, username, username, did);
|
||||
} catch (err: any) {
|
||||
if (err?.code === '23505' || /unique constraint/i.test(err?.message || '')) {
|
||||
return c.json({ error: `Username "${username}" is already taken — pick a different one.` }, 409);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Set recovery email if provided during registration
|
||||
if (email && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue