make Mailer an interface
This commit is contained in:
parent
dd2412463b
commit
08c09ffee7
10 changed files with 234 additions and 227 deletions
|
|
@ -33,21 +33,16 @@ type AuthStorer interface {
|
|||
PurgeExpiredToken() error
|
||||
}
|
||||
|
||||
// Mailer defines methods to send account emails.
|
||||
type Mailer interface {
|
||||
LoginToken(name, email string, c email.ContentLoginToken) error
|
||||
}
|
||||
|
||||
// Resource implements passwordless account authentication against a database.
|
||||
type Resource struct {
|
||||
LoginAuth *LoginTokenAuth
|
||||
TokenAuth *jwt.TokenAuth
|
||||
Store AuthStorer
|
||||
Mailer Mailer
|
||||
Mailer email.Mailer
|
||||
}
|
||||
|
||||
// NewResource returns a configured authentication resource.
|
||||
func NewResource(authStore AuthStorer, mailer Mailer) (*Resource, error) {
|
||||
func NewResource(authStore AuthStorer, mailer email.Mailer) (*Resource, error) {
|
||||
loginAuth, err := NewLoginTokenAuth()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -126,14 +121,17 @@ func (rs *Resource) login(w http.ResponseWriter, r *http.Request) {
|
|||
tokenURL, _ := url.JoinPath(rs.LoginAuth.loginURL, lt.Token)
|
||||
|
||||
go func() {
|
||||
content := email.ContentLoginToken{
|
||||
content := ContentLoginToken{
|
||||
Email: acc.Email,
|
||||
Name: acc.Name,
|
||||
URL: tokenURL,
|
||||
Token: lt.Token,
|
||||
Expiry: lt.Expiry,
|
||||
}
|
||||
if err := rs.Mailer.LoginToken(acc.Name, acc.Email, content); err != nil {
|
||||
|
||||
msg := LoginTokenEmail(acc.Name, acc.Email, content)
|
||||
|
||||
if err := rs.Mailer.Send(msg); err != nil {
|
||||
log(r).WithField("module", "email").Error(err)
|
||||
}
|
||||
}()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import (
|
|||
var (
|
||||
auth *Resource
|
||||
authStore MockAuthStore
|
||||
mailer email.MockMailer
|
||||
mailer *email.MockMailer
|
||||
ts *httptest.Server
|
||||
)
|
||||
|
||||
|
|
@ -35,7 +35,9 @@ func TestMain(m *testing.M) {
|
|||
viper.SetDefault("log_level", "error")
|
||||
|
||||
var err error
|
||||
auth, err = NewResource(&authStore, &mailer)
|
||||
|
||||
mailer = email.NewMockMailer()
|
||||
auth, err = NewResource(&authStore, mailer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
|
|
@ -72,10 +74,6 @@ func TestAuthResource_login(t *testing.T) {
|
|||
return &a, err
|
||||
}
|
||||
|
||||
mailer.LoginTokenFn = func(n, e string, c email.ContentLoginToken) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
email string
|
||||
|
|
@ -105,11 +103,11 @@ func TestAuthResource_login(t *testing.T) {
|
|||
if tc.err == ErrInvalidLogin && authStore.GetAccountByEmailInvoked {
|
||||
t.Error("GetByLoginToken invoked for invalid email")
|
||||
}
|
||||
if tc.err == nil && !mailer.LoginTokenInvoked {
|
||||
t.Error("emailService.LoginToken not invoked")
|
||||
if tc.err == nil && !mailer.SendInvoked {
|
||||
t.Error("emailService.Send not invoked")
|
||||
}
|
||||
authStore.GetAccountByEmailInvoked = false
|
||||
mailer.LoginTokenInvoked = false
|
||||
mailer.SendInvoked = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
28
auth/pwdless/emails.go
Normal file
28
auth/pwdless/emails.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package pwdless
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/dhax/go-base/email"
|
||||
)
|
||||
|
||||
// ContentLoginToken defines content for login token email template.
|
||||
type ContentLoginToken struct {
|
||||
Email string
|
||||
Name string
|
||||
URL string
|
||||
Token string
|
||||
Expiry time.Time
|
||||
}
|
||||
|
||||
// LoginTokenEmail creates and sends a login token email with provided template content.
|
||||
func LoginTokenEmail(name, address string, content ContentLoginToken) email.Message {
|
||||
return email.Message{
|
||||
From: email.NewEmail(os.Getenv("EMAIL_FROM_NAME"), os.Getenv("EMAIL_FROM_ADDRESS")),
|
||||
To: email.NewEmail(name, address),
|
||||
Subject: "Login Token",
|
||||
Template: "loginToken",
|
||||
Content: content,
|
||||
}
|
||||
}
|
||||
|
|
@ -9,9 +9,7 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var (
|
||||
errTokenNotFound = errors.New("login token not found")
|
||||
)
|
||||
var errTokenNotFound = errors.New("login token not found")
|
||||
|
||||
// LoginToken is an in-memory saved token referencing an account ID and an expiry date.
|
||||
type LoginToken struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue