From 2157392ae4379294aa5e043e7f7a72188182ba27 Mon Sep 17 00:00:00 2001 From: Qiao Han Date: Sun, 8 Dec 2024 02:09:34 +0800 Subject: [PATCH] fix: optional smtp block should not override remote --- internal/start/start.go | 2 +- pkg/config/auth.go | 66 ++++++++++++------- pkg/config/auth_test.go | 10 +++ pkg/config/config.go | 2 +- pkg/config/templates/config.toml | 1 + .../local_disabled_remote_enabled.diff | 14 ---- .../local_enabled_remote_disabled.diff | 13 ++-- 7 files changed, 63 insertions(+), 45 deletions(-) diff --git a/internal/start/start.go b/internal/start/start.go index 4315d31b7..2483b6aed 100644 --- a/internal/start/start.go +++ b/internal/start/start.go @@ -500,7 +500,7 @@ EOF fmt.Sprintf("GOTRUE_MFA_MAX_ENROLLED_FACTORS=%v", utils.Config.Auth.MFA.MaxEnrolledFactors), } - if utils.Config.Auth.Email.Smtp != nil { + if utils.Config.Auth.Email.Smtp != nil && utils.Config.Auth.Email.Smtp.IsEnabled() { env = append(env, fmt.Sprintf("GOTRUE_SMTP_HOST=%s", utils.Config.Auth.Email.Smtp.Host), fmt.Sprintf("GOTRUE_SMTP_PORT=%d", utils.Config.Auth.Email.Smtp.Port), diff --git a/pkg/config/auth.go b/pkg/config/auth.go index 5cb551cd1..3f3c435e6 100644 --- a/pkg/config/auth.go +++ b/pkg/config/auth.go @@ -115,6 +115,7 @@ type ( } smtp struct { + Enabled *bool `toml:"enabled"` Host string `toml:"host"` Port uint16 `toml:"port"` User string `toml:"user"` @@ -380,16 +381,9 @@ func (e email) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) { body.MailerOtpExp = cast.UintToIntPtr(&e.OtpExpiry) body.SecurityUpdatePasswordRequireReauthentication = &e.SecurePasswordChange body.SmtpMaxFrequency = cast.Ptr(int(e.MaxFrequency.Seconds())) + // When local config is not set, we assume platform defaults should not change if e.Smtp != nil { - body.SmtpHost = &e.Smtp.Host - body.SmtpPort = cast.Ptr(strconv.Itoa(int(e.Smtp.Port))) - body.SmtpUser = &e.Smtp.User - body.SmtpPass = &e.Smtp.Pass - body.SmtpAdminEmail = &e.Smtp.AdminEmail - body.SmtpSenderName = &e.Smtp.SenderName - } else { - // Setting a single empty string disables SMTP - body.SmtpHost = cast.Ptr("") + e.Smtp.toAuthConfigBody(body) } if len(e.Template) == 0 { return @@ -423,27 +417,14 @@ func (e *email) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) { e.OtpExpiry = cast.IntToUint(remoteConfig.MailerOtpExp) e.SecurePasswordChange = cast.Val(remoteConfig.SecurityUpdatePasswordRequireReauthentication, false) e.MaxFrequency = time.Duration(cast.Val(remoteConfig.SmtpMaxFrequency, 0)) * time.Second - // Api resets all values when SMTP is disabled - if remoteConfig.SmtpHost != nil { - e.Smtp = &smtp{ - Host: *remoteConfig.SmtpHost, - User: cast.Val(remoteConfig.SmtpUser, ""), - Pass: hashPrefix + cast.Val(remoteConfig.SmtpPass, ""), - AdminEmail: cast.Val(remoteConfig.SmtpAdminEmail, ""), - SenderName: cast.Val(remoteConfig.SmtpSenderName, ""), - } - portStr := cast.Val(remoteConfig.SmtpPort, "") - if port, err := strconv.ParseUint(portStr, 10, 16); err == nil { - e.Smtp.Port = uint16(port) - } - } else { - e.Smtp = nil + // When local config is not set, we assume platform defaults should not change + if e.Smtp != nil { + e.Smtp.fromAuthConfig(remoteConfig) } if len(e.Template) == 0 { return } var tmpl emailTemplate - // When local config is not set, we assume platform defaults should not change tmpl = e.Template["invite"] if tmpl.Subject != nil { tmpl.Subject = remoteConfig.MailerSubjectsInvite @@ -499,6 +480,41 @@ func (e *email) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) { e.Template["reauthentication"] = tmpl } +func (s smtp) IsEnabled() bool { + // If Enabled is not defined, or defined and set to true + return cast.Val(s.Enabled, true) +} + +func (s smtp) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) { + if !s.IsEnabled() { + // Setting a single empty string disables SMTP + body.SmtpHost = cast.Ptr("") + return + } + body.SmtpHost = &s.Host + body.SmtpPort = cast.Ptr(strconv.Itoa(int(s.Port))) + body.SmtpUser = &s.User + body.SmtpPass = &s.Pass + body.SmtpAdminEmail = &s.AdminEmail + body.SmtpSenderName = &s.SenderName +} + +func (s *smtp) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) { + s.Host = cast.Val(remoteConfig.SmtpHost, "") + s.User = cast.Val(remoteConfig.SmtpUser, "") + s.Pass = hashPrefix + cast.Val(remoteConfig.SmtpPass, "") + s.AdminEmail = cast.Val(remoteConfig.SmtpAdminEmail, "") + s.SenderName = cast.Val(remoteConfig.SmtpSenderName, "") + portStr := cast.Val(remoteConfig.SmtpPort, "0") + if port, err := strconv.ParseUint(portStr, 10, 16); err == nil { + s.Port = uint16(port) + } + // Api resets all values when SMTP is disabled + if enabled := len(s.Host) > 0; s.Enabled != nil { + *s.Enabled = enabled + } +} + func (s sms) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) { body.ExternalPhoneEnabled = &s.EnableSignup body.SmsMaxFrequency = cast.Ptr(int(s.MaxFrequency.Seconds())) diff --git a/pkg/config/auth_test.go b/pkg/config/auth_test.go index 057c5ccdd..aa35bcf9f 100644 --- a/pkg/config/auth_test.go +++ b/pkg/config/auth_test.go @@ -365,6 +365,7 @@ func TestEmailDiff(t *testing.T) { }, }, Smtp: &smtp{ + Enabled: cast.Ptr(true), Host: "smtp.sendgrid.net", Port: 587, User: "apikey", @@ -535,6 +536,15 @@ func TestEmailDiff(t *testing.T) { "email_change": {}, "reauthentication": {}, }, + Smtp: &smtp{ + Enabled: cast.Ptr(false), + Host: "smtp.sendgrid.net", + Port: 587, + User: "apikey", + Pass: "test-key", + AdminEmail: "admin@email.com", + SenderName: "Admin", + }, MaxFrequency: time.Minute, OtpLength: 6, OtpExpiry: 3600, diff --git a/pkg/config/config.go b/pkg/config/config.go index 938016e83..fcc2d3710 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -843,7 +843,7 @@ func (e *email) validate(fsys fs.FS) (err error) { } e.Template[name] = tmpl } - if e.Smtp != nil { + if e.Smtp != nil && e.Smtp.IsEnabled() { if len(e.Smtp.Host) == 0 { return errors.New("Missing required field in config: auth.email.smtp.host") } diff --git a/pkg/config/templates/config.toml b/pkg/config/templates/config.toml index f59dab08b..26c480c33 100644 --- a/pkg/config/templates/config.toml +++ b/pkg/config/templates/config.toml @@ -137,6 +137,7 @@ otp_expiry = 3600 # Use a production-ready SMTP server # [auth.email.smtp] +# enabled = true # host = "smtp.sendgrid.net" # port = 587 # user = "apikey" diff --git a/pkg/config/testdata/TestEmailDiff/local_disabled_remote_enabled.diff b/pkg/config/testdata/TestEmailDiff/local_disabled_remote_enabled.diff index 3123336fa..3308fd0a4 100644 --- a/pkg/config/testdata/TestEmailDiff/local_disabled_remote_enabled.diff +++ b/pkg/config/testdata/TestEmailDiff/local_disabled_remote_enabled.diff @@ -22,17 +22,3 @@ diff remote[auth] local[auth] [email.template] [email.template.confirmation] content_path = "" -@@ -71,13 +71,6 @@ - content_path = "" - [email.template.recovery] - content_path = "" --[email.smtp] --host = "smtp.sendgrid.net" --port = 587 --user = "apikey" --pass = "hash:ed64b7695a606bc6ab4fcb41fe815b5ddf1063ccbc87afe1fa89756635db520e" --admin_email = "admin@email.com" --sender_name = "Admin" - - [sms] - enable_signup = false diff --git a/pkg/config/testdata/TestEmailDiff/local_enabled_remote_disabled.diff b/pkg/config/testdata/TestEmailDiff/local_enabled_remote_disabled.diff index 24386ae91..d42967e05 100644 --- a/pkg/config/testdata/TestEmailDiff/local_enabled_remote_disabled.diff +++ b/pkg/config/testdata/TestEmailDiff/local_enabled_remote_disabled.diff @@ -1,7 +1,7 @@ diff remote[auth] local[auth] --- remote[auth] +++ local[auth] -@@ -51,28 +51,43 @@ +@@ -51,35 +51,43 @@ inactivity_timeout = "0s" [email] @@ -40,10 +40,15 @@ diff remote[auth] local[auth] +content = "" content_path = "" [email.template.recovery] --content_path = "" +content = "recovery-content" -+content_path = "" -+[email.smtp] + content_path = "" + [email.smtp] +-host = "" +-port = 0 +-user = "" +-pass = "hash:" +-admin_email = "" +-sender_name = "" +host = "smtp.sendgrid.net" +port = 587 +user = "apikey"