fix(auth): match email addresses case-insensitively everywhere

Login and the OIDC fallback match emails case-insensitively, but the
password reset lookup and the admin create and edit checks compared
exactly. An account stored as Foo@x.com never got a reset mail, and an
admin could create bob@x next to Bob@x, after which login picked
whichever row came first. The signup collision check and the first-user
count also move inside the signup transaction.
This commit is contained in:
Maurice
2026-10-07 16:07:23 +02:00
parent e7ab0fc21e
commit 63f7eab4bb
5 changed files with 53 additions and 45 deletions
+2 -2
View File
@@ -170,7 +170,7 @@ export class AdminService {
const existingUsername = await this.users.findIdByUsernameExact(username);
if (existingUsername) return { error: 'Username already taken', status: 409 };
const existingEmail = await this.users.findIdByEmailExact(email);
const existingEmail = await this.users.findIdByEmailCI(email);
if (existingEmail) return { error: 'Email already taken', status: 409 };
const passwordHash = bcrypt.hashSync(password, BCRYPT_COST);
@@ -211,7 +211,7 @@ export class AdminService {
if (conflict) return { error: 'Username already taken', status: 409 };
}
if (email && email !== user.email) {
const conflict = await this.users.findIdByEmailExactExcluding(email, userId);
const conflict = await this.users.findIdByEmailCI(email, userId);
if (conflict) return { error: 'Email already taken', status: 409 };
}