Serialize email verification and resend to preserve registration state
Foundry Go checks / check (push) Failing after 2m1s
Foundry Go checks / check (pull_request) Failing after 1m50s

This commit is contained in:
2026-11-05 18:53:50 +08:00
parent fbe0910638
commit f69575d48f
2 changed files with 85 additions and 0 deletions
+13
View File
@@ -112,6 +112,9 @@ func (s *service) registerEmail(w http.ResponseWriter, r *http.Request, project,
return err
}
defer tx.Rollback()
if _, err = tx.ExecContext(r.Context(), "SELECT pg_advisory_xact_lock(hashtextextended($1,0))", "email:"+project+":"+email); err != nil {
return err
}
verification := token()
result, err := tx.ExecContext(r.Context(), `
INSERT INTO email_registrations(project,email,password_hash,token_hash,expires_at)
@@ -167,6 +170,16 @@ func (s *service) verifyEmail(w http.ResponseWriter, r *http.Request, project st
}
defer tx.Rollback()
var email, hash string
err = tx.QueryRowContext(r.Context(), "SELECT email FROM email_registrations WHERE project=$1 AND token_hash=$2 AND expires_at>now()", project, digest(input.Token)).Scan(&email)
if errors.Is(err, sql.ErrNoRows) {
return reject(w, 400, "invalid_verification")
}
if err != nil {
return err
}
if _, err = tx.ExecContext(r.Context(), "SELECT pg_advisory_xact_lock(hashtextextended($1,0))", "email:"+project+":"+email); err != nil {
return err
}
err = tx.QueryRowContext(r.Context(), `
DELETE FROM email_registrations WHERE project=$1 AND token_hash=$2 AND expires_at>now() RETURNING email,password_hash
`, project, digest(input.Token)).Scan(&email, &hash)