Notify question authors via Resend when an admin posts the first answer.

Require email at registration (editable on profile), add a Resend mailer with idempotent first-answer sends, and keep answer saves independent of delivery.
This commit is contained in:
2026-08-22 12:39:43 -07:00
parent 35c8c9f391
commit f61b4fc7ab
23 changed files with 589 additions and 71 deletions
+14 -1
View File
@@ -129,14 +129,21 @@ func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) {
return
}
username := strings.TrimSpace(r.PostFormValue("username"))
emailRaw := r.PostFormValue("email")
password := r.PostFormValue("password")
setupSecret := r.PostFormValue("setup_secret")
p := authPage{page: s.basePage(r, "Create account"), Username: username}
p := authPage{page: s.basePage(r, "Create account"), Username: username, Email: strings.TrimSpace(emailRaw)}
if !usernameRe.MatchString(username) {
p.Error = "Username must be 320 letters, numbers, or underscores."
s.exec(w, "register", p)
return
}
email, emailErr := store.ValidateEmail(emailRaw)
if emailErr != "" {
p.Error = emailErr
s.exec(w, "register", p)
return
}
if ok, msg := passwordValid(password); !ok {
p.Error = msg
s.exec(w, "register", p)
@@ -153,6 +160,7 @@ func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) {
}
u := &store.User{
Username: username,
Email: email,
PasswordHash: string(hash),
Role: role,
}
@@ -162,6 +170,11 @@ func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) {
s.exec(w, "register", p)
return
}
if errors.Is(err, store.ErrDuplicateEmail) {
p.Error = "That email is already registered."
s.exec(w, "register", p)
return
}
log.Printf("register create: %v", err)
http.Error(w, "could not create account", http.StatusInternalServerError)
return