fix: better error handling for public key constraint

- Add try/catch in claimUsername to handle UNIQUE constraint
- Return meaningful error: 'This public key has already claimed a different username'
- Enable observability logs for better debugging
This commit is contained in:
2025-12-08 21:31:36 +01:00
parent 163e1f73d4
commit b446adaee4
2 changed files with 37 additions and 29 deletions

View File

@@ -320,36 +320,44 @@ export class D1Storage implements Storage {
const now = Date.now(); const now = Date.now();
const expiresAt = now + YEAR_IN_MS; const expiresAt = now + YEAR_IN_MS;
// Try to insert or update try {
const result = await this.db.prepare(` // Try to insert or update
INSERT INTO usernames (username, public_key, claimed_at, expires_at, last_used, metadata) const result = await this.db.prepare(`
VALUES (?, ?, ?, ?, ?, NULL) INSERT INTO usernames (username, public_key, claimed_at, expires_at, last_used, metadata)
ON CONFLICT(username) DO UPDATE SET VALUES (?, ?, ?, ?, ?, NULL)
expires_at = ?, ON CONFLICT(username) DO UPDATE SET
last_used = ? expires_at = ?,
WHERE public_key = ? last_used = ?
`).bind( WHERE public_key = ?
request.username, `).bind(
request.publicKey, request.username,
now, request.publicKey,
expiresAt, now,
now, expiresAt,
expiresAt, now,
now, expiresAt,
request.publicKey now,
).run(); request.publicKey
).run();
if ((result.meta.changes || 0) === 0) { if ((result.meta.changes || 0) === 0) {
throw new Error('Username already claimed by different public key'); throw new Error('Username already claimed by different public key');
}
return {
username: request.username,
publicKey: request.publicKey,
claimedAt: now,
expiresAt,
lastUsed: now,
};
} catch (err: any) {
// Handle UNIQUE constraint on public_key
if (err.message?.includes('UNIQUE constraint failed: usernames.public_key')) {
throw new Error('This public key has already claimed a different username');
}
throw err;
} }
return {
username: request.username,
publicKey: request.publicKey,
claimedAt: now,
expiresAt,
lastUsed: now,
};
} }
async getUsername(username: string): Promise<Username | null> { async getUsername(username: string): Promise<Username | null> {

View File

@@ -39,7 +39,7 @@ command = ""
[observability] [observability]
[observability.logs] [observability.logs]
enabled = false enabled = true
head_sampling_rate = 1 head_sampling_rate = 1
invocation_logs = true invocation_logs = true
persist = true persist = true