diff options
author | Christopher Speller <crspeller@gmail.com> | 2017-04-27 10:55:03 -0400 |
---|---|---|
committer | Joram Wilander <jwawilander@gmail.com> | 2017-04-27 10:55:03 -0400 |
commit | 9a87bb3af68216b53ee8f89d6604c715c7b85b2d (patch) | |
tree | 8c06aed890f388b228f3aefb8e398309bc73c0b9 /app/user.go | |
parent | 0e007e344bf10993529711f14c4168365c3504c3 (diff) | |
download | chat-9a87bb3af68216b53ee8f89d6604c715c7b85b2d.tar.gz chat-9a87bb3af68216b53ee8f89d6604c715c7b85b2d.tar.bz2 chat-9a87bb3af68216b53ee8f89d6604c715c7b85b2d.zip |
Creating common token store and moving email invites and verification to it (#6213)
Diffstat (limited to 'app/user.go')
-rw-r--r-- | app/user.go | 121 |
1 files changed, 91 insertions, 30 deletions
diff --git a/app/user.go b/app/user.go index 86e7cf0b0..3d33fb317 100644 --- a/app/user.go +++ b/app/user.go @@ -30,6 +30,13 @@ import ( "github.com/mattermost/platform/utils" ) +const ( + TOKEN_TYPE_PASSWORD_RECOVERY = "password_recovery" + TOKEN_TYPE_VERIFY_EMAIL = "verify_email" + PASSWORD_RECOVER_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour + VERIFY_EMAIL_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour +) + func CreateUserWithHash(user *model.User, hash string, data string) (*model.User, *model.AppError) { if err := IsUserSignUpAllowed(); err != nil { return nil, err @@ -37,7 +44,7 @@ func CreateUserWithHash(user *model.User, hash string, data string) (*model.User props := model.MapFromJson(strings.NewReader(data)) - if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { + if hash != utils.HashSha256(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { return nil, model.NewLocAppError("CreateUserWithHash", "api.user.create_user.signup_link_invalid.app_error", nil, "") } @@ -978,11 +985,9 @@ func UpdateUser(user *model.User, sendNotifications bool) (*model.User, *model.A }() if utils.Cfg.EmailSettings.RequireEmailVerification { - go func() { - if err := SendEmailChangeVerifyEmail(rusers[0].Id, rusers[0].Email, rusers[0].Locale, utils.GetSiteURL()); err != nil { - l4g.Error(err.Error()) - } - }() + if err := SendEmailVerification(rusers[0]); err != nil { + l4g.Error(err.Error()) + } } } @@ -1084,19 +1089,19 @@ func UpdatePasswordSendEmail(user *model.User, newPassword, method string) *mode return nil } -func ResetPasswordFromCode(code, newPassword string) *model.AppError { - var recovery *model.PasswordRecovery +func ResetPasswordFromToken(userSuppliedTokenString, newPassword string) *model.AppError { + var token *model.Token var err *model.AppError - if recovery, err = GetPasswordRecovery(code); err != nil { + if token, err = GetPasswordRecoveryToken(userSuppliedTokenString); err != nil { return err } else { - if model.GetMillis()-recovery.CreateAt >= model.PASSWORD_RECOVER_EXPIRY_TIME { + if model.GetMillis()-token.CreateAt >= PASSWORD_RECOVER_EXPIRY_TIME { return model.NewAppError("resetPassword", "api.user.reset_password.link_expired.app_error", nil, "", http.StatusBadRequest) } } var user *model.User - if user, err = GetUser(recovery.UserId); err != nil { + if user, err = GetUser(token.Extra); err != nil { return err } @@ -1110,7 +1115,7 @@ func ResetPasswordFromCode(code, newPassword string) *model.AppError { return err } - if err := DeletePasswordRecoveryForUser(recovery.UserId); err != nil { + if err := DeleteToken(token); err != nil { l4g.Error(err.Error()) } @@ -1128,39 +1133,42 @@ func SendPasswordReset(email string, siteURL string) (bool, *model.AppError) { return false, model.NewAppError("SendPasswordReset", "api.user.send_password_reset.sso.app_error", nil, "userId="+user.Id, http.StatusBadRequest) } - var recovery *model.PasswordRecovery - if recovery, err = CreatePasswordRecovery(user.Id); err != nil { + var token *model.Token + if token, err = CreatePasswordRecoveryToken(user.Id); err != nil { return false, err } - if _, err := SendPasswordResetEmail(email, recovery, user.Locale, siteURL); err != nil { + if _, err := SendPasswordResetEmail(email, token, user.Locale, siteURL); err != nil { return false, model.NewLocAppError("SendPasswordReset", "api.user.send_password_reset.send.app_error", nil, "err="+err.Message) } return true, nil } -func CreatePasswordRecovery(userId string) (*model.PasswordRecovery, *model.AppError) { - recovery := &model.PasswordRecovery{} - recovery.UserId = userId +func CreatePasswordRecoveryToken(userId string) (*model.Token, *model.AppError) { + token := model.NewToken(TOKEN_TYPE_PASSWORD_RECOVERY, userId) - if result := <-Srv.Store.PasswordRecovery().SaveOrUpdate(recovery); result.Err != nil { + if result := <-Srv.Store.Token().Save(token); result.Err != nil { return nil, result.Err } - return recovery, nil + return token, nil } -func GetPasswordRecovery(code string) (*model.PasswordRecovery, *model.AppError) { - if result := <-Srv.Store.PasswordRecovery().GetByCode(code); result.Err != nil { - return nil, model.NewAppError("GetPasswordRecovery", "api.user.reset_password.invalid_link.app_error", nil, result.Err.Error(), http.StatusBadRequest) +func GetPasswordRecoveryToken(token string) (*model.Token, *model.AppError) { + if result := <-Srv.Store.Token().GetByToken(token); result.Err != nil { + return nil, model.NewAppError("GetPasswordRecoveryToken", "api.user.reset_password.invalid_link.app_error", nil, result.Err.Error(), http.StatusBadRequest) } else { - return result.Data.(*model.PasswordRecovery), nil + token := result.Data.(*model.Token) + if token.Type != TOKEN_TYPE_PASSWORD_RECOVERY { + return nil, model.NewAppError("GetPasswordRecoveryToken", "api.user.reset_password.broken_token.app_error", nil, "", http.StatusBadRequest) + } + return token, nil } } -func DeletePasswordRecoveryForUser(userId string) *model.AppError { - if result := <-Srv.Store.PasswordRecovery().Delete(userId); result.Err != nil { +func DeleteToken(token *model.Token) *model.AppError { + if result := <-Srv.Store.Token().Delete(token.Token); result.Err != nil { return result.Err } @@ -1250,10 +1258,6 @@ func PermanentDeleteUser(user *model.User) *model.AppError { return result.Err } - if result := <-Srv.Store.PasswordRecovery().Delete(user.Id); result.Err != nil { - return result.Err - } - l4g.Warn(utils.T("api.user.permanent_delete_user.deleted.warn"), user.Email, user.Id) return nil @@ -1272,6 +1276,63 @@ func PermanentDeleteAllUsers() *model.AppError { return nil } +func SendEmailVerification(user *model.User) *model.AppError { + token, err := CreateVerifyEmailToken(user.Id) + if err != nil { + return err + } + + if _, err := GetStatus(user.Id); err != nil { + go SendVerifyEmail(user.Email, user.Locale, utils.GetSiteURL(), token.Token) + } else { + go SendEmailChangeVerifyEmail(user.Email, user.Locale, utils.GetSiteURL(), token.Token) + } + + return nil +} + +func VerifyEmailFromToken(userSuppliedTokenString string) *model.AppError { + var token *model.Token + var err *model.AppError + if token, err = GetVerifyEmailToken(userSuppliedTokenString); err != nil { + return err + } else { + if model.GetMillis()-token.CreateAt >= PASSWORD_RECOVER_EXPIRY_TIME { + return model.NewAppError("resetPassword", "api.user.reset_password.link_expired.app_error", nil, "", http.StatusBadRequest) + } + if err := VerifyUserEmail(token.Extra); err != nil { + return err + } + if err := DeleteToken(token); err != nil { + l4g.Error(err.Error()) + } + } + + return nil +} + +func CreateVerifyEmailToken(userId string) (*model.Token, *model.AppError) { + token := model.NewToken(TOKEN_TYPE_VERIFY_EMAIL, userId) + + if result := <-Srv.Store.Token().Save(token); result.Err != nil { + return nil, result.Err + } + + return token, nil +} + +func GetVerifyEmailToken(token string) (*model.Token, *model.AppError) { + if result := <-Srv.Store.Token().GetByToken(token); result.Err != nil { + return nil, model.NewAppError("GetVerifyEmailToken", "api.user.verify_email.bad_link.app_error", nil, result.Err.Error(), http.StatusBadRequest) + } else { + token := result.Data.(*model.Token) + if token.Type != TOKEN_TYPE_VERIFY_EMAIL { + return nil, model.NewAppError("GetVerifyEmailToken", "api.user.verify_email.broken_token.app_error", nil, "", http.StatusBadRequest) + } + return token, nil + } +} + func VerifyUserEmail(userId string) *model.AppError { if err := (<-Srv.Store.User().VerifyEmail(userId)).Err; err != nil { return err |