From ccc11c1e77d8011cec1efdadb18d8c831d62bc75 Mon Sep 17 00:00:00 2001 From: zeripath Date: Wed, 25 May 2022 12:49:59 +0100 Subject: [PATCH] Prevent NPE when cache service is disabled (#19703) (#19783) Backport #19703 The cache service can be disabled - at which point ctx.Cache will be nil and the use of it will cause an NPE. The main part of this PR is that the cache is used for restricting resending of activation mails and without this we cache we cannot restrict this. Whilst this code could be re-considered to use the db and probably should be, I think we can simply disable this code in the case that the cache is disabled. Signed-off-by: Andrew Thornton Co-authored-by: Lauris BH --- routers/web/auth/auth.go | 21 ++++++++++++--------- routers/web/auth/password.go | 8 +++++--- routers/web/user/setting/account.go | 16 ++++++++++------ 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go index 5e0b338baf..3ef9fb6541 100644 --- a/routers/web/auth/auth.go +++ b/routers/web/auth/auth.go @@ -417,7 +417,7 @@ func SignUp(ctx *context.Context) { ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey ctx.Data["PageIsSignUp"] = true - //Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true + // Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration ctx.HTML(http.StatusOK, tplSignUp) @@ -438,7 +438,7 @@ func SignUpPost(ctx *context.Context) { ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey ctx.Data["PageIsSignUp"] = true - //Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true + // Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true if setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration { ctx.Error(http.StatusForbidden) return @@ -632,8 +632,10 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth. ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.HTML(http.StatusOK, TplActivate) - if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { - log.Error("Set cache(MailResendLimit) fail: %v", err) + if setting.CacheService.Enabled { + if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { + log.Error("Set cache(MailResendLimit) fail: %v", err) + } } return } @@ -653,14 +655,15 @@ func Activate(ctx *context.Context) { } // Resend confirmation email. if setting.Service.RegisterEmailConfirm { - if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { + if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+ctx.User.LowerName) { ctx.Data["ResendLimited"] = true } else { ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) mailer.SendActivateAccountMail(ctx.Locale, ctx.User) - - if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { - log.Error("Set cache(MailResendLimit) fail: %v", err) + if setting.CacheService.Enabled { + if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { + log.Error("Set cache(MailResendLimit) fail: %v", err) + } } } } else { @@ -789,7 +792,7 @@ func ActivateEmail(ctx *context.Context) { if u, err := user_model.GetUserByID(email.UID); err != nil { log.Warn("GetUserByID: %d", email.UID) - } else { + } else if setting.CacheService.Enabled { // Allow user to validate more emails _ = ctx.Cache.Delete("MailResendLimit_" + u.LowerName) } diff --git a/routers/web/auth/password.go b/routers/web/auth/password.go index 65d5c55976..fe11554120 100644 --- a/routers/web/auth/password.go +++ b/routers/web/auth/password.go @@ -80,7 +80,7 @@ func ForgotPasswdPost(ctx *context.Context) { return } - if ctx.Cache.IsExist("MailResendLimit_" + u.LowerName) { + if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+u.LowerName) { ctx.Data["ResendLimited"] = true ctx.HTML(http.StatusOK, tplForgotPassword) return @@ -88,8 +88,10 @@ func ForgotPasswdPost(ctx *context.Context) { mailer.SendResetPasswordMail(u) - if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { - log.Error("Set cache(MailResendLimit) fail: %v", err) + if setting.CacheService.Enabled { + if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { + log.Error("Set cache(MailResendLimit) fail: %v", err) + } } ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) diff --git a/routers/web/user/setting/account.go b/routers/web/user/setting/account.go index 492b4f82c8..e29cb91f4b 100644 --- a/routers/web/user/setting/account.go +++ b/routers/web/user/setting/account.go @@ -106,7 +106,7 @@ func EmailPost(ctx *context.Context) { // Send activation Email if ctx.FormString("_method") == "SENDACTIVATION" { var address string - if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { + if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+ctx.User.LowerName) { log.Error("Send activation: activation still pending") ctx.Redirect(setting.AppSubURL + "/user/settings/account") return @@ -142,8 +142,10 @@ func EmailPost(ctx *context.Context) { } address = email.Email - if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { - log.Error("Set cache(MailResendLimit) fail: %v", err) + if setting.CacheService.Enabled { + if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { + log.Error("Set cache(MailResendLimit) fail: %v", err) + } } ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", address, timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()))) ctx.Redirect(setting.AppSubURL + "/user/settings/account") @@ -202,8 +204,10 @@ func EmailPost(ctx *context.Context) { // Send confirmation email if setting.Service.RegisterEmailConfirm { mailer.SendActivateEmailMail(ctx.User, email) - if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { - log.Error("Set cache(MailResendLimit) fail: %v", err) + if setting.CacheService.Enabled { + if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { + log.Error("Set cache(MailResendLimit) fail: %v", err) + } } ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()))) } else { @@ -271,7 +275,7 @@ func loadAccountData(ctx *context.Context) { user_model.EmailAddress CanBePrimary bool } - pendingActivation := ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) + pendingActivation := setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+ctx.User.LowerName) emails := make([]*UserEmail, len(emlist)) for i, em := range emlist { var email UserEmail