fix(auth): login resolves by EITHER username or email

Root cause of 'wrong password' right after logout->login (no redeploy): after first-run
setup sets an email, users naturally type their EMAIL in the login field, but verify()
only looked up by USERNAME -> user not found -> 'invalid credentials' shown as wrong
password. Now verify(ident) = get_user_or_none(username) OR by_email(ident). Verified:
login by username (200) and by email (200) both work with the new password.

Tests: m0/setup/e2e all pass.
This commit is contained in:
Macky
2026-08-07 21:00:15 +07:00
parent 7d778d780d
commit 1867a1aac8

View File

@@ -146,8 +146,10 @@ class UserStore:
return self.users.update(self._norm(username), must_setup=False) return self.users.update(self._norm(username), must_setup=False)
# ── auth ─────────────────────────────────────────────────────────── # ── auth ───────────────────────────────────────────────────────────
def verify(self, username: str, password: str) -> dict[str, Any]: def verify(self, ident: str, password: str) -> dict[str, Any]:
user = self.get_user_or_none(username) # Resolve by EITHER username OR email (the login form doesn't distinguish,
# and users naturally type their email after setup). Fall back to username.
user = self.get_user_or_none(ident) or self.by_email(ident)
if not user or not user.get("active", True): if not user or not user.get("active", True):
raise AuthError("invalid credentials") raise AuthError("invalid credentials")
if not check_password_hash(user["password_hash"], password): if not check_password_hash(user["password_hash"], password):