diff --git a/system/service/auth_notification.go b/system/service/auth_notification.go index 779c0759f..48c04b3e0 100644 --- a/system/service/auth_notification.go +++ b/system/service/auth_notification.go @@ -1,9 +1,12 @@ package service import ( - "bytes" "context" "fmt" + htpl "html/template" + "io/ioutil" + "net/url" + "github.com/cortezaproject/corteza-server/pkg/logger" "github.com/cortezaproject/corteza-server/pkg/mail" "github.com/cortezaproject/corteza-server/pkg/options" @@ -11,14 +14,13 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" gomail "gopkg.in/mail.v2" - htpl "html/template" - "net/url" ) type ( authNotification struct { logger *zap.Logger settings *types.AppSettings + ts TemplateService opt options.AuthOpt } @@ -27,24 +29,13 @@ type ( EmailConfirmation(ctx context.Context, lang string, emailAddress string, url string) error PasswordReset(ctx context.Context, lang string, emailAddress string, url string) error } - - authNotificationPayload struct { - EmailAddress string - URL string - Code string - BaseURL string - Logo htpl.URL - SignatureName string - SignatureEmail string - EmailHeaderEn htpl.HTML - EmailFooterEn htpl.HTML - } ) -func AuthNotification(s *types.AppSettings, opt options.AuthOpt) AuthNotificationService { +func AuthNotification(s *types.AppSettings, ts TemplateService, opt options.AuthOpt) AuthNotificationService { return &authNotification{ logger: DefaultLogger.Named("auth-notification"), settings: s, + ts: ts, opt: opt, } } @@ -54,23 +45,20 @@ func (svc authNotification) log(ctx context.Context, fields ...zapcore.Field) *z } func (svc authNotification) EmailOTP(ctx context.Context, lang string, emailAddress string, code string) error { - return svc.send(ctx, "email-otp", lang, authNotificationPayload{ - EmailAddress: emailAddress, - Code: code, + return svc.send(ctx, "auth_email_otp", lang, emailAddress, map[string]interface{}{ + "Code": code, }) } func (svc authNotification) EmailConfirmation(ctx context.Context, lang string, emailAddress string, token string) error { - return svc.send(ctx, "email-confirmation", lang, authNotificationPayload{ - EmailAddress: emailAddress, - URL: fmt.Sprintf("%s/confirm-email?token=%s", svc.opt.BaseURL, url.QueryEscape(token)), + return svc.send(ctx, "auth_email_confirmation", lang, emailAddress, map[string]interface{}{ + "URL": fmt.Sprintf("%s/confirm-email?token=%s", svc.opt.BaseURL, url.QueryEscape(token)), }) } func (svc authNotification) PasswordReset(ctx context.Context, lang string, emailAddress string, token string) error { - return svc.send(ctx, "password-reset", lang, authNotificationPayload{ - EmailAddress: emailAddress, - URL: fmt.Sprintf("%s/reset-password?token=%s", svc.opt.BaseURL, url.QueryEscape(token)), + return svc.send(ctx, "auth_email_password_reset", lang, emailAddress, map[string]interface{}{ + "URL": fmt.Sprintf("%s/reset-password?token=%s", svc.opt.BaseURL, url.QueryEscape(token)), }) } @@ -88,96 +76,59 @@ func (svc authNotification) newMail() *gomail.Message { return m } -func (svc authNotification) send(ctx context.Context, name, lang string, payload authNotificationPayload) error { +func (svc authNotification) send(ctx context.Context, name, lang, sendTo string, payload map[string]interface{}) error { var ( err error - tmp string + tmp []byte ntf = svc.newMail() ) - payload.Logo = htpl.URL(svc.settings.General.Mail.Logo) - payload.BaseURL = svc.opt.BaseURL - payload.SignatureName = svc.settings.Auth.Mail.FromName - payload.SignatureEmail = svc.settings.Auth.Mail.FromAddress - - // @todo translations - if tmp, err = svc.render(svc.settings.General.Mail.Header, payload); err != nil { - return fmt.Errorf("failed to render svc.settings.General.Mail.Header: %w", err) + // Fetch parts + st, err := svc.ts.FindByHandle(ctx, name+"_subject") + if err != nil { + return err } - payload.EmailHeaderEn = htpl.HTML(tmp) - if tmp, err = svc.render(svc.settings.General.Mail.Footer, payload); err != nil { - return fmt.Errorf("failed to render svc.settings.General.Mail.Footer: %w", err) + ct, err := svc.ts.FindByHandle(ctx, name+"_content") + if err != nil { + return err } - payload.EmailFooterEn = htpl.HTML(tmp) - ntf.SetAddressHeader("To", payload.EmailAddress, "") - // @todo translations - switch name { - case "email-confirmation": - if tmp, err = svc.render(svc.settings.Auth.Mail.EmailConfirmation.Subject, payload); err != nil { - return fmt.Errorf("failed to render svc.settings.Auth.Mail.EmailConfirmation.Subject: %w", err) - } - ntf.SetHeader("Subject", tmp) - if tmp, err = svc.render(svc.settings.Auth.Mail.EmailConfirmation.Body, payload); err != nil { - return fmt.Errorf("failed to render svc.settings.Auth.Mail.EmailConfirmation.Body: %w", err) - } - ntf.SetBody("text/html", tmp) + // Prepare payload + payload["Logo"] = htpl.URL(svc.settings.General.Mail.Logo) + payload["BaseURL"] = svc.opt.BaseURL + payload["SignatureName"] = svc.settings.Auth.Mail.FromName + payload["SignatureEmail"] = svc.settings.Auth.Mail.FromAddress + payload["EmailAddress"] = sendTo - case "password-reset": - if tmp, err = svc.render(svc.settings.Auth.Mail.PasswordReset.Subject, payload); err != nil { - return fmt.Errorf("failed to render svc.settings.Auth.Mail.PasswordReset.Subject: %w", err) - } - ntf.SetHeader("Subject", tmp) - if tmp, err = svc.render(svc.settings.Auth.Mail.PasswordReset.Body, payload); err != nil { - return fmt.Errorf("failed to render svc.settings.Auth.Mail.PasswordReset.Body: %w", err) - } - ntf.SetBody("text/html", tmp) - - case "email-otp": - // @todo move this to new template/renderer facility - ntf.SetHeader("Subject", "Login code") - - bodyTpl := `{{.EmailHeaderEn}} -
Hello,
-Enter this code into your login form: {{.Code}}