Skip to content

Commit

Permalink
feat: added integration with postmark (#484)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbarrosop authored Mar 22, 2024
1 parent dd03035 commit 243efd1
Show file tree
Hide file tree
Showing 24 changed files with 215 additions and 9 deletions.
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
module = "github.com/nhost/hasura-auth/go";
submodule = ".";

tags = [ "integration" ];
tags = [ ];

ldflags = [
"-X main.Version=${version}"
Expand Down
15 changes: 14 additions & 1 deletion go/cmd/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import (
"os"
"path/filepath"

"github.com/nhost/hasura-auth/go/controller"
"github.com/nhost/hasura-auth/go/notifications"
"github.com/nhost/hasura-auth/go/notifications/postmark"
"github.com/urfave/cli/v2"
)

func getEmailer(cCtx *cli.Context, logger *slog.Logger) (*notifications.Email, error) {
func getSMTPEmailer(cCtx *cli.Context, logger *slog.Logger) (*notifications.Email, error) {
headers := make(map[string]string)
if cCtx.String(flagSMTPAPIHedaer) != "" {
headers["X-SMTPAPI"] = cCtx.String(flagSMTPAPIHedaer)
Expand Down Expand Up @@ -66,3 +68,14 @@ func getEmailer(cCtx *cli.Context, logger *slog.Logger) (*notifications.Email, e
templates,
), nil
}

func getEmailer( //nolint:ireturn
cCtx *cli.Context,
logger *slog.Logger,
) (controller.Emailer, error) {
if cCtx.String(flagSMTPHost) == "postmark" {
return postmark.New(cCtx.String(flagSMTPSender), cCtx.String(flagSMTPPassword)), nil
}

return getSMTPEmailer(cCtx, logger)
}
2 changes: 1 addition & 1 deletion go/cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func CommandServe() *cli.Command { //nolint:funlen,maintidx
},
&cli.StringFlag{ //nolint: exhaustruct
Name: flagSMTPHost,
Usage: "SMTP Host",
Usage: "SMTP Host. If the host is 'postmark' then the Postmark API will be used. Use AUTH_SMTP_PASS as the server token, other SMTP options are ignored",
Category: "smtp",
EnvVars: []string{"AUTH_SMTP_HOST"},
},
Expand Down
1 change: 1 addition & 0 deletions go/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func ptr[T any](x T) *T {

type Emailer interface {
SendEmail(
ctx context.Context,
to string,
locale string,
templateName notifications.TemplateName,
Expand Down
8 changes: 4 additions & 4 deletions go/controller/mock/controller.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions go/controller/post_signin_passwordless_email.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func (ctrl *Controller) PostSigninPasswordlessEmail( //nolint:ireturn
}

if err := ctrl.wf.SendEmail(
ctx,
string(request.Body.Email),
user.Locale,
LinkTypePasswordlessEmail,
Expand Down
4 changes: 4 additions & 0 deletions go/controller/post_signin_passwordless_email_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func TestPostSigninPasswordlessEmail(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameSigninPasswordless,
Expand Down Expand Up @@ -255,6 +256,7 @@ func TestPostSigninPasswordlessEmail(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameSigninPasswordless,
Expand Down Expand Up @@ -381,6 +383,7 @@ func TestPostSigninPasswordlessEmail(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"fr",
notifications.TemplateNameSigninPasswordless,
Expand Down Expand Up @@ -516,6 +519,7 @@ func TestPostSigninPasswordlessEmail(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameSigninPasswordless,
Expand Down
1 change: 1 addition & 0 deletions go/controller/post_signup_email_password.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func (ctrl *Controller) postSignupEmailPasswordWithEmailVerificationOrUserDisabl
}

if err := ctrl.wf.SendEmail(
ctx,
email,
deptr(options.Locale),
LinkTypeEmailVerify,
Expand Down
1 change: 1 addition & 0 deletions go/controller/post_signup_email_password_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,7 @@ func TestPostSignupEmailPassword(t *testing.T) { //nolint:maintidx
emailer: func(ctrl *gomock.Controller) *mock.MockEmailer {
mock := mock.NewMockEmailer(ctrl)
mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameEmailVerify,
Expand Down
1 change: 1 addition & 0 deletions go/controller/post_signup_webauthn_verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ func (ctrl *Controller) postSignupWebauthnVerifyWithEmailVerificationOrUserDisab
}

if err := ctrl.wf.SendEmail(
ctx,
webauthnUser.Email,
deptr(options.Locale),
LinkTypeEmailVerify,
Expand Down
1 change: 1 addition & 0 deletions go/controller/post_signup_webauthn_verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ func TestPostSignupWebauthnVerify(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameEmailVerify,
Expand Down
1 change: 1 addition & 0 deletions go/controller/post_user_deanonymize.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func (ctrl *Controller) PostUserDeanonymize( //nolint:funlen

if ticket != "" {
if apiError = ctrl.wf.SendEmail(
ctx,
string(request.Body.Email),
*options.Locale,
linkType,
Expand Down
2 changes: 2 additions & 0 deletions go/controller/post_user_deanonymize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ func TestPostUserDeanonymize(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameEmailVerify,
Expand Down Expand Up @@ -309,6 +310,7 @@ func TestPostUserDeanonymize(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameSigninPasswordless,
Expand Down
1 change: 1 addition & 0 deletions go/controller/post_user_email_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func (ctrl *Controller) PostUserEmailChange( //nolint:ireturn
}

if err := ctrl.wf.SendEmail(
ctx,
string(request.Body.NewEmail),
updatedUser.Locale,
LinkTypeEmailConfirmChange,
Expand Down
2 changes: 2 additions & 0 deletions go/controller/post_user_email_change_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func TestPostUserEmailChange(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameEmailConfirmChange,
Expand Down Expand Up @@ -252,6 +253,7 @@ func TestPostUserEmailChange(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameEmailConfirmChange,
Expand Down
1 change: 1 addition & 0 deletions go/controller/post_user_email_send_verification_email.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func (ctrl *Controller) PostUserEmailSendVerificationEmail( //nolint:ireturn
}

if err := ctrl.wf.SendEmail(
ctx,
user.Email.String,
user.Locale,
LinkTypeEmailVerify,
Expand Down
3 changes: 3 additions & 0 deletions go/controller/post_user_email_send_verification_email_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func TestPostUserEmailSendVerificationEmail(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameEmailVerify,
Expand Down Expand Up @@ -136,6 +137,7 @@ func TestPostUserEmailSendVerificationEmail(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameEmailVerify,
Expand Down Expand Up @@ -210,6 +212,7 @@ func TestPostUserEmailSendVerificationEmail(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNameEmailVerify,
Expand Down
1 change: 1 addition & 0 deletions go/controller/post_user_password_reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (ctrl *Controller) PostUserPasswordReset( //nolint:ireturn
}

if err := ctrl.wf.SendEmail(
ctx,
string(request.Body.Email),
user.Locale,
LinkTypePasswordReset,
Expand Down
2 changes: 2 additions & 0 deletions go/controller/post_user_password_reset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func TestPostUserPasswordReset(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNamePasswordReset,
Expand Down Expand Up @@ -134,6 +135,7 @@ func TestPostUserPasswordReset(t *testing.T) { //nolint:maintidx
mock := mock.NewMockEmailer(ctrl)

mock.EXPECT().SendEmail(
gomock.Any(),
"[email protected]",
"en",
notifications.TemplateNamePasswordReset,
Expand Down
2 changes: 2 additions & 0 deletions go/controller/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ func (wf *Workflows) ChangeEmail(
}

func (wf *Workflows) SendEmail(
ctx context.Context,
to string,
locale string,
linkType LinkType,
Expand All @@ -485,6 +486,7 @@ func (wf *Workflows) SendEmail(
}

if err := wf.email.SendEmail(
ctx,
to,
locale,
templateName,
Expand Down
3 changes: 2 additions & 1 deletion go/notifications/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package notifications

import (
"bytes"
"context"
"fmt"
"net/smtp"
)
Expand Down Expand Up @@ -61,7 +62,7 @@ func (sm *Email) Send(to, subject, contents string, headers map[string]string) e
}

func (sm *Email) SendEmail(
to string, locale string, templateName TemplateName, data TemplateData,
_ context.Context, to string, locale string, templateName TemplateName, data TemplateData,
) error {
body, subject, err := sm.templates.Render(locale, templateName, data)
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion go/notifications/email_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package notifications_test

import (
"context"
"log/slog"
"net/smtp"
"testing"
Expand Down Expand Up @@ -99,7 +100,11 @@ func TestEmailSendEmailVerify(t *testing.T) {
}

if err := mail.SendEmail(
"user@localhost", tc.locale, notifications.TemplateNameEmailVerify, tc.data,
context.Background(),
"user@localhost",
tc.locale,
notifications.TemplateNameEmailVerify,
tc.data,
); err != nil {
t.Fatalf("error sending email: %v", err)
}
Expand Down
Loading

0 comments on commit 243efd1

Please sign in to comment.