func ResetPasswordEmail(uid string) { db, err := NewDb() if err != nil { logrus.Fatal(err.Error()) } _, err = model.FetchAnswer(db, uid) if err != nil { logrus.WithFields(logrus.Fields{ "uid": uid, "error": err, }).Error("Failed to fetch security answer. Please run newacct to setup user account.") return } token, err := createToken(uid) if err != nil { logrus.Fatal(err.Error()) } app, err := NewApplication() if err != nil { logrus.Fatal(err.Error()) } vars := map[string]interface{}{ "link": fmt.Sprintf("%s/auth/resetpw/%s", viper.GetString("email_link_base"), model.SignToken(RESET_SALT, token.Token))} err = app.SendEmail(token.Email, fmt.Sprintf("[%s] Please reset your password", viper.GetString("email_prefix")), "reset-password.txt", vars) if err != nil { logrus.WithFields(logrus.Fields{ "uid": uid, "error": err, }).Error("failed send email to user") } }
func forgotPassword(app *Application, r *http.Request) error { uid := r.FormValue("uid") if len(uid) == 0 { return errors.New("Please provide a user name.") } _, err := model.FetchTokenByUser(app.db, uid, viper.GetInt("setup_max_age")) if err == nil { logrus.WithFields(logrus.Fields{ "uid": uid, }).Error("Forgotpw: user already has active token") return nil } client := NewIpaClient(true) userRec, err := client.UserShow(uid) if err != nil { logrus.WithFields(logrus.Fields{ "uid": uid, "error": err, }).Error("Forgotpw: invalid uid") return nil } if len(userRec.Email) == 0 { logrus.WithFields(logrus.Fields{ "uid": uid, }).Error("Forgotpw: missing email address") return nil } _, err = model.FetchAnswer(app.db, uid) if err != nil { logrus.WithFields(logrus.Fields{ "uid": uid, "error": err, }).Error("Forgotpw: Failed to fetch security answer") return nil } token, err := model.NewToken(app.db, uid, string(userRec.Email)) if err != nil { logrus.WithFields(logrus.Fields{ "uid": uid, "error": err, }).Error("Forgotpw: Failed to create token") return nil } vars := map[string]interface{}{ "link": fmt.Sprintf("%s/auth/resetpw/%s", viper.GetString("email_link_base"), model.SignToken(RESET_SALT, token.Token))} err = app.SendEmail(token.Email, fmt.Sprintf("[%s] Please reset your password", viper.GetString("email_prefix")), "reset-password.txt", vars) if err != nil { logrus.WithFields(logrus.Fields{ "uid": uid, "error": err, }).Error("Forgotpw: failed send email to user") } return nil }
func ResetPasswordHandler(app *Application) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { tk, ok := model.VerifyToken(RESET_SALT, mux.Vars(r)["token"]) if !ok { w.WriteHeader(http.StatusNotFound) renderTemplate(w, app.templates["404.html"], nil) return } token, err := model.FetchToken(app.db, tk, viper.GetInt("reset_max_age")) if err != nil { logrus.WithFields(logrus.Fields{ "error": err.Error(), }).Error("Failed to fetch token from database") w.WriteHeader(http.StatusNotFound) renderTemplate(w, app.templates["404.html"], nil) return } if token.Attempts > viper.GetInt("max_attempts") { logrus.WithFields(logrus.Fields{ "token": token.Token, "uid": token.UserName, }).Error("Too many attempts for token.") w.WriteHeader(http.StatusNotFound) renderTemplate(w, app.templates["404.html"], nil) return } answer, err := model.FetchAnswer(app.db, token.UserName) if err != nil { logrus.WithFields(logrus.Fields{ "uid": token.UserName, "error": err, }).Error("Failed to fetch security answer") w.WriteHeader(http.StatusNotFound) renderTemplate(w, app.templates["404.html"], nil) return } message := "" completed := false if r.Method == "POST" { err := resetPassword(app, answer, token, r) if err != nil { message = err.Error() completed = false err := model.IncrementToken(app.db, token.Token) if err != nil { logrus.WithFields(logrus.Fields{ "error": err.Error(), }).Error("Failed to increment token attempts") } } else { completed = true err = app.SendEmail(token.Email, fmt.Sprintf("[%s] Your password change confirmation", viper.GetString("email_prefix")), "reset-password-confirm.txt", nil) if err != nil { logrus.WithFields(logrus.Fields{ "uid": token.UserName, "error": err, }).Error("failed to send reset confirmation email to user") } } } vars := map[string]interface{}{ "token": nosurf.Token(r), "uid": token.UserName, "completed": completed, "question": answer.Question, "message": message} renderTemplate(w, app.templates["reset-password.html"], vars) }) }