fix(auth): commit the account on registration so a pre-approved sign-up isn't lost
_register_account() flushed the new User but relied on someone else to commit: upsert_pending_invite() commits only when it actually writes an invite row, and _issue_token() runs only when SMTP is enabled. For an email an admin had ALREADY approved, on an instance where email is unavailable, neither fired — the session closed and the account was rolled back. The would-be user got the uniform "ok" and no account, could not sign in, and re-registering was a silent no-op. Commit explicitly after the invite upsert (a no-op when upsert already committed the same transaction). Three DB-lane regression tests cover the pre-approved no-SMTP path (fails without the fix), the unknown-email path that always worked, and the pre-approved path with SMTP on.
This commit is contained in:
@@ -636,7 +636,14 @@ def _register_account(email: str, password: str) -> None:
|
||||
# no-op as the pre-check hit — roll back and stop.
|
||||
db.rollback()
|
||||
return
|
||||
upsert_pending_invite(db, email) # admin-approval gate (commits)
|
||||
upsert_pending_invite(db, email) # admin-approval gate (commits only when it writes a row)
|
||||
# Persist the account ourselves. upsert_pending_invite commits only when it actually inserts
|
||||
# (or revives) an invite row, and _issue_token below only runs with SMTP on — so for an email
|
||||
# the admin had ALREADY approved, on an instance with no SMTP, nothing along this path
|
||||
# committed and the flushed user was silently rolled back when the session closed. The
|
||||
# would-be user got a uniform "ok" and no account. Commit unconditionally; it is a no-op
|
||||
# when upsert already committed the same transaction.
|
||||
db.commit()
|
||||
if email_ok:
|
||||
raw = _issue_token(db, user, "verify", VERIFY_TTL)
|
||||
# Fragment (#), not a query token: keeps the token out of proxy/access logs + Referer (SB3).
|
||||
|
||||
Reference in New Issue
Block a user