From 3d520fd32b10b35e1528c3483cf7843e1101f0ae Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Thu, 25 Jul 2024 18:45:11 -0700 Subject: [PATCH] Include username in password reset email Resolves #23. --- pkg/server/database.go | 25 +++++++++++++------------ pkg/server/database_disabled.go | 4 ++-- pkg/server/server_full.go | 6 +++--- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/pkg/server/database.go b/pkg/server/database.go index 69295d8..6a9f77c 100644 --- a/pkg/server/database.go +++ b/pkg/server/database.go @@ -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) { diff --git a/pkg/server/database_disabled.go b/pkg/server/database_disabled.go index 2dd8ed5..7a3bd80 100644 --- a/pkg/server/database_disabled.go +++ b/pkg/server/database_disabled.go @@ -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) { diff --git a/pkg/server/server_full.go b/pkg/server/server_full.go index 965107e..54f80d8 100644 --- a/pkg/server/server_full.go +++ b/pkg/server/server_full.go @@ -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(`

Invalid or expired password reset link.

`)) return } - w.Write([]byte(`

Your bgammon.org password has been reset.

Your new password is ` + newPassword + ``)) + w.Write([]byte(`

Your bgammon.org password has been reset.

Your username is ` + username + `

Your new password is ` + newPassword + ``)) } func (s *server) handleMatch(w http.ResponseWriter, r *http.Request) {