Skip to content

Commit

Permalink
(NOBIDS) prevent pw reset if not allowed
Browse files Browse the repository at this point in the history
  • Loading branch information
guybrush committed Mar 11, 2024
1 parent f00ee6d commit 5fd8756
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- +goose Up
-- +goose StatementBegin
SELECT 'up SQL query - add column users.password_reset_not_allowed';
ALTER TABLE users ADD COLUMN IF NOT EXISTS password_reset_not_allowed BOOLEAN NOT NULL DEFAULT FALSE;
-- +goose StatementEnd

-- +goose Down
-- +goose StatementBegin
SELECT 'down SQL query - drop column users.password_reset_not_allowed';
ALTER TABLE users DROP COLUMN IF EXISTS password_reset_not_allowed;
-- +goose StatementEnd
25 changes: 20 additions & 5 deletions handlers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,12 +553,18 @@ func RequestResetPasswordPost(w http.ResponseWriter, r *http.Request) {
}

var rateLimitError *types.RateLimitError
var passwordResetNotAllowedError *types.PasswordResetNotAllowedError
err = sendPasswordResetEmail(email)
if err != nil && !errors.As(err, &rateLimitError) {
logger.Errorf("error sending reset-email: %v", err)
utils.SetFlash(w, r, authSessionName, authInternalServerErrorFlashMsg)
} else if err != nil && errors.As(err, &rateLimitError) {
utils.SetFlash(w, r, authSessionName, fmt.Sprintf("Error: The ratelimit for sending emails has been exceeded, please try again in %v.", err.(*types.RateLimitError).TimeLeft.Round(time.Second)))
if err != nil {
switch {
case errors.As(err, &passwordResetNotAllowedError):
utils.SetFlash(w, r, authSessionName, "Error: Password reset is not allowed for this user.")
case errors.As(err, &rateLimitError):
utils.SetFlash(w, r, authSessionName, fmt.Sprintf("Error: The ratelimit for sending emails has been exceeded, please try again in %v.", err.(*types.RateLimitError).TimeLeft.Round(time.Second)))
default:
logger.Errorf("error sending reset-email: %v", err)
utils.SetFlash(w, r, authSessionName, authInternalServerErrorFlashMsg)
}
} else {
utils.SetFlash(w, r, authSessionName, "An email has been sent which contains a link to reset your password.")
}
Expand Down Expand Up @@ -736,6 +742,15 @@ func sendPasswordResetEmail(email string) error {
}
defer tx.Rollback()

var passwordResetNotAllowed bool
err = tx.Get(&passwordResetNotAllowed, "SELECT COALESCE(password_reset_not_allowed, true) FROM users WHERE email = $1", email)
if err != nil {
return fmt.Errorf("error getting password_reset_not_allowed: %w", err)
}
if passwordResetNotAllowed {
return fmt.Errorf("password-reset not allowed for user: %v", email)
}

var lastTs *time.Time
err = tx.Get(&lastTs, "SELECT password_reset_ts FROM users WHERE email = $1", email)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
Expand Down
18 changes: 13 additions & 5 deletions handlers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -1046,13 +1046,14 @@ func UserUpdatePasswordPost(w http.ResponseWriter, r *http.Request) {
pwdOld := r.FormValue("old-password")

currentUser := struct {
ID int64 `db:"id"`
Email string `db:"email"`
Password string `db:"password"`
Confirmed bool `db:"email_confirmed"`
ID int64 `db:"id"`
Email string `db:"email"`
Password string `db:"password"`
Confirmed bool `db:"email_confirmed"`
PasswordResetNotAllowed bool `db:"password_reset_not_allowed"`
}{}

err = db.FrontendWriterDB.Get(&currentUser, "SELECT id, email, password, email_confirmed FROM users WHERE id = $1", user.UserID)
err = db.FrontendWriterDB.Get(&currentUser, "SELECT id, email, password, email_confirmed, password_reset_not_allowed FROM users WHERE id = $1", user.UserID)
if err != nil {
if err != sql.ErrNoRows {
logger.Errorf("error retrieving password for user %v: %v", user.UserID, err)
Expand All @@ -1063,6 +1064,13 @@ func UserUpdatePasswordPost(w http.ResponseWriter, r *http.Request) {
return
}

if currentUser.PasswordResetNotAllowed {
session.AddFlash("Error: Password reset is not allowed for this account!")
session.Save(r, w)
http.Redirect(w, r, "/user/settings", http.StatusSeeOther)
return
}

if !currentUser.Confirmed {
session.AddFlash("Error: Email has not been confirmed, please click the link in the email we sent you or <a href='/resend'>resend link</a>!")
session.Save(r, w)
Expand Down
7 changes: 7 additions & 0 deletions types/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,13 @@ type StakeWithUsPageData struct {
FlashMessage string
RecaptchaKey string
}

type PasswordResetNotAllowedError struct{}

func (e *PasswordResetNotAllowedError) Error() string {
return "password reset not allowed for this account"
}

type RateLimitError struct {
TimeLeft time.Duration
}
Expand Down

0 comments on commit 5fd8756

Please sign in to comment.