Include username in password reset email

Resolves #23.
This commit is contained in:
Trevor Slocum 2024-07-25 18:45:11 -07:00
parent 5df43b9539
commit 3d520fd32b
3 changed files with 18 additions and 17 deletions

View file

@ -281,54 +281,55 @@ func resetAccount(mailServer string, resetSalt string, email []byte) error {
return nil
}
func confirmResetAccount(resetSalt string, passwordSalt string, id int, key string) (string, error) {
func confirmResetAccount(resetSalt string, passwordSalt string, id int, key string) (string, string, error) {
dbLock.Lock()
defer dbLock.Unlock()
if db == nil {
return "", nil
return "", "", nil
} else if id == 0 {
return "", fmt.Errorf("no id provided")
return "", "", fmt.Errorf("no id provided")
} else if len(strings.TrimSpace(key)) == 0 {
return "", fmt.Errorf("no reset key provided")
return "", "", fmt.Errorf("no reset key provided")
}
tx, err := begin()
if err != nil {
return "", err
return "", "", err
}
defer tx.Commit(context.Background())
var result int
err = tx.QueryRow(context.Background(), "SELECT COUNT(*) FROM account WHERE id = $1 AND reset != 0", id).Scan(&result)
if err != nil {
return "", err
return "", "", err
} else if result == 0 {
return "", nil
return "", "", nil
}
var username string
var reset int
err = tx.QueryRow(context.Background(), "SELECT reset FROM account WHERE id = $1", id).Scan(&reset)
err = tx.QueryRow(context.Background(), "SELECT username, reset FROM account WHERE id = $1", id).Scan(&username, &reset)
if err != nil {
return "", err
return "", "", err
}
h := sha256.New()
h.Write([]byte(fmt.Sprintf("%d/%d", id, reset) + resetSalt))
hash := fmt.Sprintf("%x", h.Sum(nil))[0:16]
if key != hash {
return "", nil
return "", "", nil
}
newPassword := randomAlphanumeric(7)
passwordHash, err := argon2id.CreateHash(newPassword+passwordSalt, passwordArgon2id)
if err != nil {
return "", err
return "", "", err
}
_, err = tx.Exec(context.Background(), "UPDATE account SET password = $1, reset = reset - 1 WHERE id = $2", passwordHash, id)
return newPassword, err
return username, newPassword, err
}
func accountByID(id int) (*account, error) {

View file

@ -27,8 +27,8 @@ func resetAccount(mailServer string, resetSalt string, email []byte) error {
return nil
}
func confirmResetAccount(resetSalt string, passwordSalt string, id int, key string) (string, error) {
return "", nil
func confirmResetAccount(resetSalt string, passwordSalt string, id int, key string) (string, string, error) {
return "", "", nil
}
func accountByID(id int) (*account, error) {

View file

@ -237,17 +237,17 @@ func (s *server) handleResetPassword(w http.ResponseWriter, r *http.Request) {
}
key := vars["key"]
newPassword, err := confirmResetAccount(s.resetSalt, s.passwordSalt, id, key)
username, newPassword, err := confirmResetAccount(s.resetSalt, s.passwordSalt, id, key)
if err != nil {
log.Printf("failed to reset password: %s", err)
}
w.Header().Set("Content-Type", "text/html")
if err != nil || newPassword == "" {
if err != nil || username == "" || newPassword == "" {
w.Write([]byte(`<!DOCTYPE html><html><body><h1>Invalid or expired password reset link.</h1></body></html>`))
return
}
w.Write([]byte(`<!DOCTYPE html><html><body><h1>Your bgammon.org password has been reset.</h1>Your new password is <b>` + newPassword + `</b></body></html>`))
w.Write([]byte(`<!DOCTYPE html><html><body><h1>Your bgammon.org password has been reset.</h1>Your username is <b>` + username + `</b><br><br>Your new password is <b>` + newPassword + `</b></body></html>`))
}
func (s *server) handleMatch(w http.ResponseWriter, r *http.Request) {