1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-02-03 13:21:22 +02:00

Fix confirm module to use global config

This commit is contained in:
Kris Runzer 2015-02-15 20:35:32 -08:00
parent 127ef8ea17
commit d0dd19689b
3 changed files with 54 additions and 53 deletions

View File

@ -8,7 +8,6 @@ import (
"encoding/base64"
"errors"
"fmt"
"io"
"net/http"
"net/url"
@ -17,7 +16,7 @@ import (
)
const (
UserConfirmToken = "confirm_token"
UserConfirmToken = "confirmToken"
UserConfirmed = "confirmed"
UserEmail = "email"
@ -43,30 +42,23 @@ func init() {
}
type Confirm struct {
logger io.Writer
storer authboss.ConfirmStorer
config *authboss.Config
emailTemplates views.Templates
}
func (c *Confirm) Initialize(config *authboss.Config) (err error) {
func (c *Confirm) Initialize() (err error) {
var ok bool
c.storer, ok = config.Storer.(authboss.ConfirmStorer)
if config.Storer == nil || !ok {
storer, ok := authboss.Cfg.Storer.(authboss.ConfirmStorer)
if storer == nil || !ok {
return errors.New("confirm: Need a ConfirmStorer.")
}
c.logger = config.LogWriter
c.config = config
c.emailTemplates, err = views.Get(config.LayoutEmail, config.ViewsPath, tplConfirmHTML, tplConfirmText)
c.emailTemplates, err = views.Get(authboss.Cfg.LayoutEmail, authboss.Cfg.ViewsPath, tplConfirmHTML, tplConfirmText)
if err != nil {
return err
}
config.Callbacks.Before(authboss.EventGet, c.BeforeGet)
config.Callbacks.After(authboss.EventRegister, c.AfterRegister)
authboss.Cfg.Callbacks.Before(authboss.EventGet, c.BeforeGet)
authboss.Cfg.Callbacks.After(authboss.EventRegister, c.AfterRegister)
return nil
}
@ -97,12 +89,12 @@ func (c *Confirm) BeforeGet(ctx *authboss.Context) error {
// AfterRegister ensures the account is not activated.
func (c *Confirm) AfterRegister(ctx *authboss.Context) {
if ctx.User == nil {
fmt.Fprintln(c.logger, "confirm: user not loaded in AfterRegister callback")
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: user not loaded in AfterRegister callback")
}
token := make([]byte, 32)
if _, err := rand.Read(token); err != nil {
fmt.Fprintln(c.logger, "confirm: failed to produce random token:", err)
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: failed to produce random token:", err)
}
sum := md5.Sum(token)
@ -110,13 +102,13 @@ func (c *Confirm) AfterRegister(ctx *authboss.Context) {
username, _ := ctx.User.String(authboss.UserName)
if err := ctx.SaveUser(username, c.config.Storer); err != nil {
fmt.Fprintln(c.logger, "confirm: failed to save user's token:", err)
if err := ctx.SaveUser(username, authboss.Cfg.Storer); err != nil {
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: failed to save user's token:", err)
return
}
if email, ok := ctx.User.String(UserEmail); !ok {
fmt.Fprintln(c.logger, "confirm: user has no e-mail address to send to, could not send confirm e-mail")
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: user has no e-mail address to send to, could not send confirm e-mail")
} else {
goConfirmEmail(c, email, base64.URLEncoding.EncodeToString(sum[:]))
}
@ -128,28 +120,28 @@ var goConfirmEmail = func(c *Confirm, to, token string) {
// confirmEmail sends a confirmation e-mail.
func (c *Confirm) confirmEmail(to, token string) {
url := fmt.Sprintf("%s/confirm?%s=%s", c.config.HostName, url.QueryEscape(FormValueConfirm), url.QueryEscape(token))
url := fmt.Sprintf("%s/confirm?%s=%s", authboss.Cfg.HostName, url.QueryEscape(FormValueConfirm), url.QueryEscape(token))
var htmlEmailBody, textEmailBody *bytes.Buffer
var err error
if htmlEmailBody, err = c.emailTemplates.ExecuteTemplate(tplConfirmHTML, url); err != nil {
fmt.Fprintln(c.logger, "confirm: failed to build html template:", err)
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: failed to build html template:", err)
return
}
if textEmailBody, err = c.emailTemplates.ExecuteTemplate(tplConfirmText, url); err != nil {
fmt.Fprintln(c.logger, "confirm: failed to build plaintext template:", err)
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: failed to build plaintext template:", err)
return
}
if err := c.config.Mailer.Send(authboss.Email{
if err := authboss.Cfg.Mailer.Send(authboss.Email{
To: []string{to},
From: c.config.EmailFrom,
Subject: c.config.EmailSubjectPrefix + "Confirm New Account",
From: authboss.Cfg.EmailFrom,
Subject: authboss.Cfg.EmailSubjectPrefix + "Confirm New Account",
TextBody: textEmailBody.String(),
HTMLBody: htmlEmailBody.String(),
}); err != nil {
fmt.Fprintln(c.logger, "confirm: failed to build plaintext template:", err)
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: failed to build plaintext template:", err)
}
}
@ -157,26 +149,26 @@ func (c *Confirm) confirmHandler(ctx *authboss.Context, w http.ResponseWriter, r
token, ok := ctx.FirstFormValue(FormValueConfirm)
if len(token) == 0 || !ok {
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
fmt.Fprintln(c.logger, "confirm: no confirm token found in get")
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: no confirm token found in get")
return
}
tok, err := base64.URLEncoding.DecodeString(token)
if err != nil {
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
fmt.Fprintf(c.logger, "confirm: confirm token failed to decode %q => %v\n", token, err)
fmt.Fprintf(authboss.Cfg.LogWriter, "confirm: confirm token failed to decode %q => %v\n", token, err)
return
}
dbTok := base64.StdEncoding.EncodeToString(tok)
user, err := c.storer.ConfirmUser(dbTok)
user, err := authboss.Cfg.Storer.(authboss.ConfirmStorer).ConfirmUser(dbTok)
if err == authboss.ErrUserNotFound {
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
fmt.Fprintln(c.logger, "confirm: token not found", err)
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: token not found", err)
return
} else if err != nil {
w.WriteHeader(500)
fmt.Fprintln(c.logger, "confirm: error retrieving user token:", err)
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: error retrieving user token:", err)
return
}
@ -188,15 +180,15 @@ func (c *Confirm) confirmHandler(ctx *authboss.Context, w http.ResponseWriter, r
key, ok := ctx.User.String(authboss.UserName)
if !ok {
w.WriteHeader(500)
fmt.Fprintln(c.logger, "confirm: user had no key field")
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: user had no key field")
return
}
ctx.SessionStorer.Put(authboss.SessionKey, key)
ctx.SessionStorer.Put(authboss.FlashSuccessKey, "Successfully confirmed your account.")
if err := ctx.SaveUser(key, c.config.Storer); err != nil {
fmt.Fprintln(c.logger, "confirm: failed to clear the user's token:", err)
if err := ctx.SaveUser(key, authboss.Cfg.Storer); err != nil {
fmt.Fprintln(authboss.Cfg.LogWriter, "confirm: failed to clear the user's token:", err)
return
}

View File

@ -9,38 +9,26 @@ import (
)
func setup() *Confirm {
config := authboss.NewConfig()
config.Storer = mocks.NewMockStorer()
config.LayoutEmail = template.Must(template.New("").Parse(`email ^_^`))
authboss.NewConfig()
authboss.Cfg.Storer = mocks.NewMockStorer()
authboss.Cfg.LayoutEmail = template.Must(template.New("").Parse(`email ^_^`))
c := &Confirm{}
if err := c.Initialize(config); err != nil {
if err := c.Initialize(); err != nil {
panic(err)
}
return c
}
func TestConfirm_Initialize(t *testing.T) {
authboss.NewConfig()
c := &Confirm{}
if err := c.Initialize(authboss.NewConfig()); err == nil {
if err := c.Initialize(); err == nil {
t.Error("Should cry about not having a storer.")
}
c = setup()
if c.config == nil {
t.Error("Missing config")
}
if c.logger == nil {
t.Error("Missing logger")
}
if c.storer == nil {
t.Error("Missing storer")
}
if c.emailTemplates == nil {
t.Error("Missing email templates")
}

View File

@ -32,6 +32,7 @@ type MockStorer struct {
DelTokensErr string
UseTokenErr string
RecoverUserErr string
ConfirmUserErr string
}
func NewMockStorer() *MockStorer {
@ -138,6 +139,26 @@ func (m *MockStorer) RecoverUser(token string) (result interface{}, err error) {
return nil, authboss.ErrUserNotFound
}
func (m *MockStorer) ConfirmUser(confirmToken string) (result interface{}, err error) {
if len(m.ConfirmUserErr) > 0 {
return nil, errors.New(m.ConfirmUserErr)
}
for _, user := range m.Users {
if user["confirm_token"] == confirmToken {
u := &MockUser{}
if err = user.Bind(u); err != nil {
panic(err)
}
return u, nil
}
}
return nil, authboss.ErrUserNotFound
}
// MockFailStorer is used for testing module initialize functions that recover more than the base storer
type MockFailStorer struct{}