Skip to content

Commit

Permalink
fix: pushdown mailer
Browse files Browse the repository at this point in the history
  • Loading branch information
J0 committed Mar 25, 2024
1 parent 96f7a68 commit c63aaa5
Show file tree
Hide file tree
Showing 11 changed files with 24 additions and 28 deletions.
2 changes: 1 addition & 1 deletion internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func (a *API) HealthCheck(w http.ResponseWriter, r *http.Request) error {
}

// Mailer returns NewMailer with the current tenant config
func (a *API) Mailer(ctx context.Context) mailer.Mailer {
func (a *API) Mailer() mailer.Mailer {
config := a.config
return mailer.NewMailer(config)
}
3 changes: 1 addition & 2 deletions internal/api/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,9 @@ func (a *API) createAccountFromExternalIdentity(tx *storage.Connection, r *http.
} else {
emailConfirmationSent := false
if decision.CandidateEmail.Email != "" {
mailer := a.Mailer(ctx)
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
if terr = sendConfirmation(tx, user, mailer, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, models.ImplicitFlow); terr != nil {
if terr = a.sendConfirmation(tx, user, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, models.ImplicitFlow); terr != nil {
if errors.Is(terr, MaxFrequencyLimitError) {
return nil, tooManyRequestsError(ErrorCodeOverEmailSendRateLimit, "For security purposes, you can only request this once every minute")
}
Expand Down
3 changes: 1 addition & 2 deletions internal/api/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,9 @@ func (a *API) linkIdentityToUser(r *http.Request, ctx context.Context, tx *stora
return nil, terr
}
if !userData.Metadata.EmailVerified {
mailer := a.Mailer(ctx)
referrer := utilities.GetReferrer(r, a.config)
externalURL := getExternalHost(ctx)
if terr := sendConfirmation(tx, targetUser, mailer, a.config.SMTP.MaxFrequency, referrer, externalURL, a.config.Mailer.OtpLength, models.ImplicitFlow); terr != nil {
if terr := a.sendConfirmation(tx, targetUser, a.config.SMTP.MaxFrequency, referrer, externalURL, a.config.Mailer.OtpLength, models.ImplicitFlow); terr != nil {
if errors.Is(terr, MaxFrequencyLimitError) {
return nil, tooManyRequestsError(ErrorCodeOverSMSSendRateLimit, "For security purposes, you can only request this once every minute")
}
Expand Down
3 changes: 1 addition & 2 deletions internal/api/invite.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,9 @@ func (a *API) Invite(w http.ResponseWriter, r *http.Request) error {
return terr
}

mailer := a.Mailer(ctx)
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
if err := sendInvite(tx, user, mailer, referrer, externalURL, config.Mailer.OtpLength); err != nil {
if err := a.sendInvite(tx, user, referrer, externalURL, config.Mailer.OtpLength); err != nil {
return internalServerError("Error inviting user").WithInternalError(err)
}
return nil
Expand Down
3 changes: 1 addition & 2 deletions internal/api/magic_link.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,9 @@ func (a *API) MagicLink(w http.ResponseWriter, r *http.Request) error {
if terr := models.NewAuditLogEntry(r, tx, user, models.UserRecoveryRequestedAction, "", nil); terr != nil {
return terr
}
mailer := a.Mailer(ctx)
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
return a.sendMagicLink(tx, user, mailer, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, flowType)
return a.sendMagicLink(tx, user, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, flowType)
})
if err != nil {
if errors.Is(err, MaxFrequencyLimitError) {
Expand Down
21 changes: 13 additions & 8 deletions internal/api/mail.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/supabase/auth/internal/api/provider"
"github.com/supabase/auth/internal/conf"
"github.com/supabase/auth/internal/crypto"
"github.com/supabase/auth/internal/mailer"
"github.com/supabase/auth/internal/models"
"github.com/supabase/auth/internal/storage"
"github.com/supabase/auth/internal/utilities"
Expand Down Expand Up @@ -45,7 +44,7 @@ func (a *API) adminGenerateLink(w http.ResponseWriter, r *http.Request) error {
ctx := r.Context()
db := a.db.WithContext(ctx)
config := a.config
mailer := a.Mailer(ctx)
mailer := a.Mailer()
adminUser := getAdminUser(ctx)
params := &GenerateLinkParams{}
if err := retrieveRequestParams(r, params); err != nil {
Expand Down Expand Up @@ -263,7 +262,8 @@ func (a *API) adminGenerateLink(w http.ResponseWriter, r *http.Request) error {
return sendJSON(w, http.StatusOK, resp)
}

func sendConfirmation(tx *storage.Connection, u *models.User, mailer mailer.Mailer, maxFrequency time.Duration, referrerURL string, externalURL *url.URL, otpLength int, flowType models.FlowType) error {
func (a *API) sendConfirmation(tx *storage.Connection, u *models.User, maxFrequency time.Duration, referrerURL string, externalURL *url.URL, otpLength int, flowType models.FlowType) error {
mailer := a.Mailer()
var err error
if u.ConfirmationSentAt != nil && !u.ConfirmationSentAt.Add(maxFrequency).Before(time.Now()) {
return MaxFrequencyLimitError
Expand All @@ -290,7 +290,8 @@ func sendConfirmation(tx *storage.Connection, u *models.User, mailer mailer.Mail
return nil
}

func sendInvite(tx *storage.Connection, u *models.User, mailer mailer.Mailer, referrerURL string, externalURL *url.URL, otpLength int) error {
func (a *API) sendInvite(tx *storage.Connection, u *models.User, referrerURL string, externalURL *url.URL, otpLength int) error {
mailer := a.Mailer()
var err error
oldToken := u.ConfirmationToken
otp, err := crypto.GenerateOtp(otpLength)
Expand All @@ -314,7 +315,8 @@ func sendInvite(tx *storage.Connection, u *models.User, mailer mailer.Mailer, re
return nil
}

func (a *API) sendPasswordRecovery(tx *storage.Connection, u *models.User, mailer mailer.Mailer, maxFrequency time.Duration, referrerURL string, externalURL *url.URL, otpLength int, flowType models.FlowType) error {
func (a *API) sendPasswordRecovery(tx *storage.Connection, u *models.User, maxFrequency time.Duration, referrerURL string, externalURL *url.URL, otpLength int, flowType models.FlowType) error {
mailer := a.Mailer()
var err error
if u.RecoverySentAt != nil && !u.RecoverySentAt.Add(maxFrequency).Before(time.Now()) {
return MaxFrequencyLimitError
Expand Down Expand Up @@ -342,7 +344,8 @@ func (a *API) sendPasswordRecovery(tx *storage.Connection, u *models.User, maile
return nil
}

func (a *API) sendReauthenticationOtp(tx *storage.Connection, u *models.User, mailer mailer.Mailer, maxFrequency time.Duration, otpLength int) error {
func (a *API) sendReauthenticationOtp(tx *storage.Connection, u *models.User, maxFrequency time.Duration, otpLength int) error {
mailer := a.Mailer()
var err error
if u.ReauthenticationSentAt != nil && !u.ReauthenticationSentAt.Add(maxFrequency).Before(time.Now()) {
return MaxFrequencyLimitError
Expand All @@ -369,7 +372,8 @@ func (a *API) sendReauthenticationOtp(tx *storage.Connection, u *models.User, ma
return nil
}

func (a *API) sendMagicLink(tx *storage.Connection, u *models.User, mailer mailer.Mailer, maxFrequency time.Duration, referrerURL string, externalURL *url.URL, otpLength int, flowType models.FlowType) error {
func (a *API) sendMagicLink(tx *storage.Connection, u *models.User, maxFrequency time.Duration, referrerURL string, externalURL *url.URL, otpLength int, flowType models.FlowType) error {
mailer := a.Mailer()
var err error
// since Magic Link is just a recovery with a different template and behaviour
// around new users we will reuse the recovery db timer to prevent potential abuse
Expand Down Expand Up @@ -400,8 +404,9 @@ func (a *API) sendMagicLink(tx *storage.Connection, u *models.User, mailer maile
}

// sendEmailChange sends out an email change token to the new email.
func (a *API) sendEmailChange(tx *storage.Connection, config *conf.GlobalConfiguration, u *models.User, mailer mailer.Mailer, email, referrerURL string, externalURL *url.URL, otpLength int, flowType models.FlowType) error {
func (a *API) sendEmailChange(tx *storage.Connection, config *conf.GlobalConfiguration, u *models.User, email, referrerURL string, externalURL *url.URL, otpLength int, flowType models.FlowType) error {
var err error
mailer := a.Mailer()
if u.EmailChangeSentAt != nil && !u.EmailChangeSentAt.Add(config.SMTP.MaxFrequency).Before(time.Now()) {
return MaxFrequencyLimitError
}
Expand Down
3 changes: 1 addition & 2 deletions internal/api/reauthenticate.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ func (a *API) Reauthenticate(w http.ResponseWriter, r *http.Request) error {
return terr
}
if email != "" {
mailer := a.Mailer(ctx)
return a.sendReauthenticationOtp(tx, user, mailer, config.SMTP.MaxFrequency, config.Mailer.OtpLength)
return a.sendReauthenticationOtp(tx, user, config.SMTP.MaxFrequency, config.Mailer.OtpLength)
} else if phone != "" {
smsProvider, terr := sms_provider.GetSmsProvider(*config)
if terr != nil {
Expand Down
3 changes: 1 addition & 2 deletions internal/api/recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ func (a *API) Recover(w http.ResponseWriter, r *http.Request) error {
if terr := models.NewAuditLogEntry(r, tx, user, models.UserRecoveryRequestedAction, "", nil); terr != nil {
return terr
}
mailer := a.Mailer(ctx)
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
return a.sendPasswordRecovery(tx, user, mailer, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, flowType)
return a.sendPasswordRecovery(tx, user, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, flowType)
})
if err != nil {
if errors.Is(err, MaxFrequencyLimitError) {
Expand Down
5 changes: 2 additions & 3 deletions internal/api/resend.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ func (a *API) Resend(w http.ResponseWriter, r *http.Request) error {
}

messageID := ""
mailer := a.Mailer(ctx)
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
err = db.Transaction(func(tx *storage.Connection) error {
Expand All @@ -125,7 +124,7 @@ func (a *API) Resend(w http.ResponseWriter, r *http.Request) error {
return terr
}
// PKCE not implemented yet
return sendConfirmation(tx, user, mailer, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, models.ImplicitFlow)
return a.sendConfirmation(tx, user, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, models.ImplicitFlow)
case smsVerification:
if terr := models.NewAuditLogEntry(r, tx, user, models.UserRecoveryRequestedAction, "", nil); terr != nil {
return terr
Expand All @@ -140,7 +139,7 @@ func (a *API) Resend(w http.ResponseWriter, r *http.Request) error {
}
messageID = mID
case emailChangeVerification:
return a.sendEmailChange(tx, config, user, mailer, user.EmailChange, referrer, externalURL, config.Mailer.OtpLength, models.ImplicitFlow)
return a.sendEmailChange(tx, config, user, user.EmailChange, referrer, externalURL, config.Mailer.OtpLength, models.ImplicitFlow)
case phoneChangeVerification:
smsProvider, terr := sms_provider.GetSmsProvider(*config)
if terr != nil {
Expand Down
3 changes: 1 addition & 2 deletions internal/api/signup.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ func (a *API) Signup(w http.ResponseWriter, r *http.Request) error {
return internalServerError("Database error updating user").WithInternalError(terr)
}
} else {
mailer := a.Mailer(ctx)
referrer := utilities.GetReferrer(r, config)
if terr = models.NewAuditLogEntry(r, tx, user, models.UserConfirmationRequestedAction, "", map[string]interface{}{
"provider": params.Provider,
Expand All @@ -248,7 +247,7 @@ func (a *API) Signup(w http.ResponseWriter, r *http.Request) error {
}
}
externalURL := getExternalHost(ctx)
if terr = sendConfirmation(tx, user, mailer, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, flowType); terr != nil {
if terr = a.sendConfirmation(tx, user, config.SMTP.MaxFrequency, referrer, externalURL, config.Mailer.OtpLength, flowType); terr != nil {
if errors.Is(terr, MaxFrequencyLimitError) {
now := time.Now()
left := user.ConfirmationSentAt.Add(config.SMTP.MaxFrequency).Sub(now) / time.Second
Expand Down
3 changes: 1 addition & 2 deletions internal/api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ func (a *API) UserUpdate(w http.ResponseWriter, r *http.Request) error {
}

if params.Email != "" && params.Email != user.GetEmail() {
mailer := a.Mailer(ctx)
referrer := utilities.GetReferrer(r, config)
flowType := getFlowFromChallenge(params.CodeChallenge)
if isPKCEFlow(flowType) {
Expand All @@ -205,7 +204,7 @@ func (a *API) UserUpdate(w http.ResponseWriter, r *http.Request) error {

}
externalURL := getExternalHost(ctx)
if terr = a.sendEmailChange(tx, config, user, mailer, params.Email, referrer, externalURL, config.Mailer.OtpLength, flowType); terr != nil {
if terr = a.sendEmailChange(tx, config, user, params.Email, referrer, externalURL, config.Mailer.OtpLength, flowType); terr != nil {
if errors.Is(terr, MaxFrequencyLimitError) {
return tooManyRequestsError(ErrorCodeOverEmailSendRateLimit, "For security purposes, you can only request this once every 60 seconds")
}
Expand Down

0 comments on commit c63aaa5

Please sign in to comment.