mirror of
https://github.com/volatiletech/authboss.git
synced 2024-11-28 08:58:38 +02:00
Change config to be global. Updated most modules and tests.
This commit is contained in:
parent
1aa0da808c
commit
bab1475b72
38
auth/auth.go
38
auth/auth.go
@ -3,16 +3,13 @@ package auth
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
"gopkg.in/authboss.v0"
|
"gopkg.in/authboss.v0"
|
||||||
"gopkg.in/authboss.v0/internal/views"
|
"gopkg.in/authboss.v0/internal/views"
|
||||||
|
|
||||||
"html/template"
|
|
||||||
|
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -44,19 +41,14 @@ type AuthPage struct {
|
|||||||
type Auth struct {
|
type Auth struct {
|
||||||
routes authboss.RouteTable
|
routes authboss.RouteTable
|
||||||
storageOptions authboss.StorageOptions
|
storageOptions authboss.StorageOptions
|
||||||
storer authboss.Storer
|
|
||||||
logoutRedirect string
|
|
||||||
loginRedirect string
|
|
||||||
logger io.Writer
|
|
||||||
templates map[string]*template.Template
|
templates map[string]*template.Template
|
||||||
callbacks *authboss.Callbacks
|
|
||||||
|
|
||||||
isRememberLoaded bool
|
isRememberLoaded bool
|
||||||
isRecoverLoaded bool
|
isRecoverLoaded bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Auth) Initialize(config *authboss.Config) (err error) {
|
func (a *Auth) Initialize() (err error) {
|
||||||
if a.templates, err = views.Get(config.Layout, config.ViewsPath, pageLogin); err != nil {
|
if a.templates, err = views.Get(authboss.Cfg.Layout, authboss.Cfg.ViewsPath, pageLogin); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,11 +60,6 @@ func (a *Auth) Initialize(config *authboss.Config) (err error) {
|
|||||||
attrUsername: authboss.String,
|
attrUsername: authboss.String,
|
||||||
attrPassword: authboss.String,
|
attrPassword: authboss.String,
|
||||||
}
|
}
|
||||||
a.storer = config.Storer
|
|
||||||
a.logoutRedirect = config.AuthLogoutRoute
|
|
||||||
a.loginRedirect = config.AuthLoginSuccessRoute
|
|
||||||
a.logger = config.LogWriter
|
|
||||||
a.callbacks = config.Callbacks
|
|
||||||
|
|
||||||
a.isRememberLoaded = authboss.IsLoaded("remember")
|
a.isRememberLoaded = authboss.IsLoaded("remember")
|
||||||
a.isRecoverLoaded = authboss.IsLoaded("recover")
|
a.isRecoverLoaded = authboss.IsLoaded("recover")
|
||||||
@ -93,7 +80,7 @@ func (a *Auth) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
|||||||
case methodGET:
|
case methodGET:
|
||||||
if _, ok := ctx.SessionStorer.Get(authboss.SessionKey); ok {
|
if _, ok := ctx.SessionStorer.Get(authboss.SessionKey); ok {
|
||||||
if halfAuthed, ok := ctx.SessionStorer.Get(authboss.HalfAuthKey); !ok || halfAuthed == "false" {
|
if halfAuthed, ok := ctx.SessionStorer.Get(authboss.HalfAuthKey); !ok || halfAuthed == "false" {
|
||||||
http.Redirect(w, r, a.loginRedirect, http.StatusFound)
|
http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,14 +93,13 @@ func (a *Auth) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
|||||||
|
|
||||||
tpl := a.templates[pageLogin]
|
tpl := a.templates[pageLogin]
|
||||||
tpl.Execute(w, page)
|
tpl.Execute(w, page)
|
||||||
// tpl.ExecuteTemplate(w, tpl.Name(), page)
|
|
||||||
case methodPOST:
|
case methodPOST:
|
||||||
u, ok := ctx.FirstPostFormValue("username")
|
u, ok := ctx.FirstPostFormValue("username")
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Fprintln(a.logger, errors.New("auth: Expected postFormValue 'username' to be in the context"))
|
fmt.Fprintln(authboss.Cfg.LogWriter, errors.New("auth: Expected postFormValue 'username' to be in the context"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.callbacks.FireBefore(authboss.EventAuth, ctx); err != nil {
|
if err := authboss.Cfg.Callbacks.FireBefore(authboss.EventAuth, ctx); err != nil {
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
|
|
||||||
tpl := a.templates[pageLogin]
|
tpl := a.templates[pageLogin]
|
||||||
@ -122,11 +108,11 @@ func (a *Auth) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
|||||||
|
|
||||||
p, ok := ctx.FirstPostFormValue("password")
|
p, ok := ctx.FirstPostFormValue("password")
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Fprintln(a.logger, errors.New("auth: Expected postFormValue 'password' to be in the context"))
|
fmt.Fprintln(authboss.Cfg.LogWriter, errors.New("auth: Expected postFormValue 'password' to be in the context"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.authenticate(ctx, u, p); err != nil {
|
if err := a.authenticate(ctx, u, p); err != nil {
|
||||||
fmt.Fprintln(a.logger, err)
|
fmt.Fprintln(authboss.Cfg.LogWriter, err)
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
tpl := a.templates[pageLogin]
|
tpl := a.templates[pageLogin]
|
||||||
tpl.ExecuteTemplate(w, tpl.Name(), AuthPage{"invalid username and/or password", u, a.isRememberLoaded, a.isRecoverLoaded, "", ""})
|
tpl.ExecuteTemplate(w, tpl.Name(), AuthPage{"invalid username and/or password", u, a.isRememberLoaded, a.isRecoverLoaded, "", ""})
|
||||||
@ -134,9 +120,9 @@ func (a *Auth) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.SessionStorer.Put(authboss.SessionKey, u)
|
ctx.SessionStorer.Put(authboss.SessionKey, u)
|
||||||
a.callbacks.FireAfter(authboss.EventAuth, ctx)
|
authboss.Cfg.Callbacks.FireAfter(authboss.EventAuth, ctx)
|
||||||
|
|
||||||
http.Redirect(w, r, a.loginRedirect, http.StatusFound)
|
http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound)
|
||||||
default:
|
default:
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
@ -145,7 +131,7 @@ func (a *Auth) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
|||||||
func (a *Auth) authenticate(ctx *authboss.Context, username, password string) error {
|
func (a *Auth) authenticate(ctx *authboss.Context, username, password string) error {
|
||||||
var userInter interface{}
|
var userInter interface{}
|
||||||
var err error
|
var err error
|
||||||
if userInter, err = a.storer.Get(username, nil); err != nil {
|
if userInter, err = authboss.Cfg.Storer.Get(username, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +158,7 @@ func (a *Auth) logoutHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
|||||||
switch r.Method {
|
switch r.Method {
|
||||||
case methodGET:
|
case methodGET:
|
||||||
ctx.SessionStorer.Del(authboss.SessionKey)
|
ctx.SessionStorer.Del(authboss.SessionKey)
|
||||||
http.Redirect(w, r, a.logoutRedirect, http.StatusFound)
|
http.Redirect(w, r, authboss.Cfg.AuthLogoutRoute, http.StatusFound)
|
||||||
default:
|
default:
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
/*import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -33,10 +33,8 @@ func getCompiledTemplate(path string, data interface{}) (b *bytes.Buffer, err er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuth_Storage(t *testing.T) {
|
func TestAuth_Storage(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
a := &Auth{}
|
a := &Auth{}
|
||||||
if err := a.Initialize(authboss.NewConfig()); err != nil {
|
if err := a.Initialize(); err != nil {
|
||||||
t.Errorf("Unexpected config error: %v", err)
|
t.Errorf("Unexpected config error: %v", err)
|
||||||
}
|
}
|
||||||
options := a.Storage()
|
options := a.Storage()
|
||||||
@ -61,10 +59,8 @@ func TestAuth_Storage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuth_Routes(t *testing.T) {
|
func TestAuth_Routes(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
a := &Auth{}
|
a := &Auth{}
|
||||||
if err := a.Initialize(authboss.NewConfig()); err != nil {
|
if err := a.Initialize(); err != nil {
|
||||||
t.Errorf("Unexpected config error: %v", err)
|
t.Errorf("Unexpected config error: %v", err)
|
||||||
}
|
}
|
||||||
routes := a.Routes()
|
routes := a.Routes()
|
||||||
@ -86,21 +82,9 @@ func TestAuth_Routes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuth_loginHandlerFunc_GET(t *testing.T) {
|
func TestAuth_loginHandlerFunc_GET(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
Config *authboss.Config
|
|
||||||
}{
|
|
||||||
{authboss.NewConfig()},
|
|
||||||
{&authboss.Config{}},
|
|
||||||
{&authboss.Config{ViewsPath: "views"}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
a := &Auth{}
|
a := &Auth{}
|
||||||
if err := a.Initialize(test.Config); err != nil {
|
if err := a.Initialize(); err != nil {
|
||||||
t.Errorf("%d> Unexpected config error: %v", i, err)
|
t.Errorf("Unexpected config error: %v", err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := http.NewRequest("GET", "/login", nil)
|
r, err := http.NewRequest("GET", "/login", nil)
|
||||||
@ -111,28 +95,22 @@ func TestAuth_loginHandlerFunc_GET(t *testing.T) {
|
|||||||
|
|
||||||
ctx, err := authboss.ContextFromRequest(r)
|
ctx, err := authboss.ContextFromRequest(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%d> Unexpected error '%s'", i, err)
|
t.Errorf("Unexpected error '%s'", err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
ctx.SessionStorer = testClientStorer{}
|
ctx.SessionStorer = testClientStorer{}
|
||||||
|
|
||||||
a.loginHandlerFunc(ctx, w, r)
|
a.loginHandlerFunc(ctx, w, r)
|
||||||
|
|
||||||
if tpl, err := getCompiledTemplate("views/login.tpl", nil); err != nil {
|
if tpl, err := getCompiledTemplate("views/login.tpl", nil); err != nil {
|
||||||
t.Errorf("%d> Unexpected error '%s'", i, err)
|
t.Errorf("Unexpected error '%s'", err)
|
||||||
continue
|
|
||||||
} else {
|
} else {
|
||||||
if !bytes.Equal(tpl.Bytes(), w.Body.Bytes()) {
|
if !bytes.Equal(tpl.Bytes(), w.Body.Bytes()) {
|
||||||
t.Errorf("%d> Expected '%s', got '%s'", i, tpl.Bytes(), w.Body.Bytes())
|
t.Errorf("Expected '%s', got '%s'", tpl.Bytes(), w.Body.Bytes())
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuth_loginHandlerFunc_POST(t *testing.T) {
|
func TestAuth_loginHandlerFunc_POST(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Username, Password string
|
Username, Password string
|
||||||
StatusCode int
|
StatusCode int
|
||||||
@ -141,17 +119,16 @@ func TestAuth_loginHandlerFunc_POST(t *testing.T) {
|
|||||||
BodyData *AuthPage
|
BodyData *AuthPage
|
||||||
}{
|
}{
|
||||||
{"john", "1234", http.StatusFound, true, "/dashboard", nil},
|
{"john", "1234", http.StatusFound, true, "/dashboard", nil},
|
||||||
{"jane", "1234", http.StatusForbidden, false, "", &AuthPage{"invalid username and/or password", "jane", false, false}},
|
{"jane", "1234", http.StatusForbidden, false, "", &AuthPage{"invalid username and/or password", "jane", false, false, "", ""}},
|
||||||
{"mike", "", http.StatusForbidden, false, "", &AuthPage{"invalid username and/or password", "jane", false, false}},
|
{"mike", "", http.StatusForbidden, false, "", &AuthPage{"invalid username and/or password", "jane", false, false, "", ""}},
|
||||||
}
|
}
|
||||||
|
|
||||||
c := authboss.NewConfig()
|
authboss.Cfg.Storer = NewMockUserStorer()
|
||||||
c.Storer = NewMockUserStorer()
|
authboss.Cfg.AuthLoginSuccessRoute = "/dashboard"
|
||||||
c.AuthLoginSuccessRoute = "/dashboard"
|
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
a := &Auth{}
|
a := &Auth{}
|
||||||
if err := a.Initialize(c); err != nil {
|
if err := a.Initialize(); err != nil {
|
||||||
t.Errorf("%d> Unexpected config error: %v", i, err)
|
t.Errorf("%d> Unexpected config error: %v", i, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -211,8 +188,6 @@ func TestAuth_loginHandlerFunc_POST(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuth_loginHandlerFunc_OtherMethods(t *testing.T) {
|
func TestAuth_loginHandlerFunc_OtherMethods(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
a := Auth{}
|
a := Auth{}
|
||||||
methods := []string{"HEAD", "PUT", "DELETE", "TRACE", "CONNECT"}
|
methods := []string{"HEAD", "PUT", "DELETE", "TRACE", "CONNECT"}
|
||||||
|
|
||||||
@ -233,10 +208,9 @@ func TestAuth_loginHandlerFunc_OtherMethods(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuth_logoutHandlerFunc_GET(t *testing.T) {
|
func TestAuth_logoutHandlerFunc_GET(t *testing.T) {
|
||||||
t.Parallel()
|
authboss.Cfg.AuthLogoutRoute = "/dashboard"
|
||||||
|
|
||||||
a := Auth{}
|
a := Auth{}
|
||||||
if err := a.Initialize(&authboss.Config{AuthLogoutRoute: "/dashboard"}); err != nil {
|
if err := a.Initialize(); err != nil {
|
||||||
t.Errorf("Unexpeced config error '%s'", err)
|
t.Errorf("Unexpeced config error '%s'", err)
|
||||||
}
|
}
|
||||||
r, err := http.NewRequest("GET", "/logout", nil)
|
r, err := http.NewRequest("GET", "/logout", nil)
|
||||||
@ -267,8 +241,6 @@ func TestAuth_logoutHandlerFunc_GET(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuth_logoutHandlerFunc_OtherMethods(t *testing.T) {
|
func TestAuth_logoutHandlerFunc_OtherMethods(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
a := Auth{}
|
a := Auth{}
|
||||||
methods := []string{"HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"}
|
methods := []string{"HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"}
|
||||||
|
|
||||||
@ -287,3 +259,4 @@ func TestAuth_logoutHandlerFunc_OtherMethods(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
27
authboss.go
27
authboss.go
@ -8,26 +8,15 @@ Remember Me tokens, or passwords.
|
|||||||
package authboss // import "gopkg.in/authboss.v0"
|
package authboss // import "gopkg.in/authboss.v0"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// Init authboss and it's loaded modules.
|
||||||
cfg *Config
|
func Init() error {
|
||||||
)
|
|
||||||
|
|
||||||
// Init authboss and it's loaded modules with a configuration.
|
|
||||||
func Init(config *Config) error {
|
|
||||||
if config.Storer == nil {
|
|
||||||
return errors.New("configuration must provide a storer.")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg = config
|
|
||||||
|
|
||||||
for name, mod := range modules {
|
for name, mod := range modules {
|
||||||
fmt.Fprintf(cfg.LogWriter, "%-10s Initializing\n", "["+name+"]")
|
fmt.Fprintf(Cfg.LogWriter, "%-10s Initializing\n", "["+name+"]")
|
||||||
if err := mod.Initialize(config); err != nil {
|
if err := mod.Initialize(); err != nil {
|
||||||
return fmt.Errorf("[%s] Error Initializing: %v", name, err)
|
return fmt.Errorf("[%s] Error Initializing: %v", name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +26,7 @@ func Init(config *Config) error {
|
|||||||
|
|
||||||
// CurrentUser retrieves the current user from the session and the database.
|
// CurrentUser retrieves the current user from the session and the database.
|
||||||
func CurrentUser(w http.ResponseWriter, r *http.Request) (interface{}, error) {
|
func CurrentUser(w http.ResponseWriter, r *http.Request) (interface{}, error) {
|
||||||
sessions := cfg.SessionStoreMaker(w, r)
|
sessions := Cfg.SessionStoreMaker(w, r)
|
||||||
key, ok := sessions.Get(SessionKey)
|
key, ok := sessions.Get(SessionKey)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -48,17 +37,17 @@ func CurrentUser(w http.ResponseWriter, r *http.Request) (interface{}, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.LoadUser(key, cfg.Storer)
|
err = ctx.LoadUser(key, Cfg.Storer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cfg.Callbacks.FireBefore(EventGet, ctx)
|
err = Cfg.Callbacks.FireBefore(EventGet, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg.Storer.Get(key, ModuleAttrMeta)
|
return Cfg.Storer.Get(key, ModuleAttrMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrentUserP retrieves the current user but panics if it's not available for
|
// CurrentUserP retrieves the current user but panics if it's not available for
|
||||||
|
@ -4,45 +4,34 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(main *testing.M) {
|
func TestMain(main *testing.M) {
|
||||||
RegisterModule("testmodule", testMod)
|
RegisterModule("testmodule", testMod)
|
||||||
Init(NewConfig())
|
Init()
|
||||||
code := main.Run()
|
code := main.Run()
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthBossInit(t *testing.T) {
|
func TestAuthBossInit(t *testing.T) {
|
||||||
c := NewConfig()
|
NewConfig()
|
||||||
|
err := Init()
|
||||||
err := Init(c)
|
|
||||||
if err == nil || !strings.Contains(err.Error(), "storer") {
|
|
||||||
t.Error("Expected error about a storer, got:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Storer = mockStorer{}
|
|
||||||
err = Init(c)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("Unexpected error:", err)
|
t.Error("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
if testMod.c == nil {
|
|
||||||
t.Error("Expected the modules to be passed the config.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthBossRouter(t *testing.T) {
|
func TestAuthBossRouter(t *testing.T) {
|
||||||
c := NewConfig()
|
NewConfig()
|
||||||
c.Storer = mockStorer{}
|
Cfg.Storer = mockStorer{}
|
||||||
c.CookieStoreMaker = func(_ http.ResponseWriter, _ *http.Request) ClientStorer {
|
Cfg.CookieStoreMaker = func(_ http.ResponseWriter, _ *http.Request) ClientStorer {
|
||||||
return mockClientStore{}
|
return mockClientStore{}
|
||||||
}
|
}
|
||||||
c.SessionStoreMaker = SessionStoreMaker(c.CookieStoreMaker)
|
Cfg.SessionStoreMaker = SessionStoreMaker(Cfg.CookieStoreMaker)
|
||||||
c.MountPath = "/candycanes"
|
Cfg.MountPath = "/candycanes"
|
||||||
|
|
||||||
if err := Init(c); err != nil {
|
if err := Init(); err != nil {
|
||||||
t.Error("Unexpected error:", err)
|
t.Error("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
router := NewRouter()
|
router := NewRouter()
|
||||||
@ -58,13 +47,13 @@ func TestAuthBossRouter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthBossCurrentUser(t *testing.T) {
|
func TestAuthBossCurrentUser(t *testing.T) {
|
||||||
c := NewConfig()
|
NewConfig()
|
||||||
c.Storer = mockStorer{"joe": Attributes{"email": "john@john.com", "password": "lies"}}
|
Cfg.Storer = mockStorer{"joe": Attributes{"email": "john@john.com", "password": "lies"}}
|
||||||
c.SessionStoreMaker = func(_ http.ResponseWriter, _ *http.Request) ClientStorer {
|
Cfg.SessionStoreMaker = func(_ http.ResponseWriter, _ *http.Request) ClientStorer {
|
||||||
return mockClientStore{SessionKey: "joe"}
|
return mockClientStore{SessionKey: "joe"}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Init(c); err != nil {
|
if err := Init(); err != nil {
|
||||||
t.Error("Unexpected error:", err)
|
t.Error("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,9 @@ const (
|
|||||||
layoutEmailTpl = "layoutEmail.tpl"
|
layoutEmailTpl = "layoutEmail.tpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Cfg is the singleton instance of Config
|
||||||
|
var Cfg *Config = NewConfig()
|
||||||
|
|
||||||
// Config holds all the configuration for both authboss and it's modules.
|
// Config holds all the configuration for both authboss and it's modules.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// MountPath is the path to mount the router at.
|
// MountPath is the path to mount the router at.
|
||||||
@ -64,7 +67,6 @@ type Config struct {
|
|||||||
Mailer Mailer
|
Mailer Mailer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig creates a new config full of default values ready to override.
|
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
layout, err := views.AssetToTemplate(layoutTpl)
|
layout, err := views.AssetToTemplate(layoutTpl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -29,14 +29,10 @@ func init() {
|
|||||||
authboss.RegisterModule("expire", E)
|
authboss.RegisterModule("expire", E)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Expire struct {
|
type Expire struct{}
|
||||||
window time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Expire) Initialize(config *authboss.Config) error {
|
func (e *Expire) Initialize() error {
|
||||||
e.window = config.ExpireAfter
|
authboss.Cfg.Callbacks.Before(authboss.EventGet, e.BeforeAuth)
|
||||||
|
|
||||||
config.Callbacks.Before(authboss.EventGet, e.BeforeAuth)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -54,7 +50,7 @@ func (e *Expire) BeforeAuth(ctx *authboss.Context) error {
|
|||||||
if ok {
|
if ok {
|
||||||
if date, err := time.Parse(time.RFC3339, dateStr); err != nil {
|
if date, err := time.Parse(time.RFC3339, dateStr); err != nil {
|
||||||
Touch(ctx.SessionStorer)
|
Touch(ctx.SessionStorer)
|
||||||
} else if time.Now().UTC().After(date.Add(e.window)) {
|
} else if time.Now().UTC().After(date.Add(authboss.Cfg.ExpireAfter)) {
|
||||||
ctx.SessionStorer.Del(authboss.SessionKey)
|
ctx.SessionStorer.Del(authboss.SessionKey)
|
||||||
return ErrExpired
|
return ErrExpired
|
||||||
}
|
}
|
||||||
|
@ -9,21 +9,8 @@ import (
|
|||||||
"gopkg.in/authboss.v0/internal/mocks"
|
"gopkg.in/authboss.v0/internal/mocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExpire(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
config := authboss.NewConfig()
|
|
||||||
config.ExpireAfter = time.Hour
|
|
||||||
E.Initialize(config)
|
|
||||||
|
|
||||||
if E.window != time.Hour {
|
|
||||||
t.Error("Config not loaded properly:", E.window)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExpire_Touch(t *testing.T) {
|
func TestExpire_Touch(t *testing.T) {
|
||||||
t.Parallel()
|
authboss.NewConfig()
|
||||||
|
|
||||||
session := mocks.NewMockClientStorer()
|
session := mocks.NewMockClientStorer()
|
||||||
|
|
||||||
if _, ok := session.Get(UserLastAction); ok {
|
if _, ok := session.Get(UserLastAction); ok {
|
||||||
@ -40,9 +27,9 @@ func TestExpire_Touch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestExpire_BeforeAuth(t *testing.T) {
|
func TestExpire_BeforeAuth(t *testing.T) {
|
||||||
t.Parallel()
|
authboss.NewConfig()
|
||||||
|
authboss.Cfg.ExpireAfter = time.Hour
|
||||||
expire := &Expire{window: time.Hour}
|
expire := &Expire{}
|
||||||
session := mocks.NewMockClientStorer()
|
session := mocks.NewMockClientStorer()
|
||||||
|
|
||||||
ctx := mocks.MockRequestContext()
|
ctx := mocks.MockRequestContext()
|
||||||
@ -82,6 +69,7 @@ func (t *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestExpire_Middleware(t *testing.T) {
|
func TestExpire_Middleware(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
session := mocks.NewMockClientStorer()
|
session := mocks.NewMockClientStorer()
|
||||||
session.Values = map[string]string{
|
session.Values = map[string]string{
|
||||||
authboss.SessionKey: "username",
|
authboss.SessionKey: "username",
|
||||||
|
49
lock/lock.go
49
lock/lock.go
@ -4,7 +4,6 @@ package lock
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/authboss.v0"
|
"gopkg.in/authboss.v0"
|
||||||
@ -30,30 +29,18 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Lock struct {
|
type Lock struct {
|
||||||
storer authboss.Storer
|
|
||||||
logger io.Writer
|
|
||||||
|
|
||||||
attempts int
|
|
||||||
window time.Duration
|
|
||||||
duration time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Lock) Initialize(config *authboss.Config) error {
|
func (l *Lock) Initialize() error {
|
||||||
if config.Storer == nil {
|
if authboss.Cfg.Storer == nil {
|
||||||
return errors.New("lock: Need a Storer.")
|
return errors.New("lock: Need a Storer.")
|
||||||
}
|
}
|
||||||
|
|
||||||
l.logger = config.LogWriter
|
|
||||||
|
|
||||||
l.attempts = config.LockAfter
|
|
||||||
l.window = config.LockWindow
|
|
||||||
l.duration = config.LockDuration
|
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
config.Callbacks.Before(authboss.EventGet, l.BeforeAuth)
|
authboss.Cfg.Callbacks.Before(authboss.EventGet, l.BeforeAuth)
|
||||||
config.Callbacks.Before(authboss.EventAuth, l.BeforeAuth)
|
authboss.Cfg.Callbacks.Before(authboss.EventAuth, l.BeforeAuth)
|
||||||
config.Callbacks.After(authboss.EventAuth, l.AfterAuth)
|
authboss.Cfg.Callbacks.After(authboss.EventAuth, l.AfterAuth)
|
||||||
config.Callbacks.After(authboss.EventAuthFail, l.AfterAuthFail)
|
authboss.Cfg.Callbacks.After(authboss.EventAuthFail, l.AfterAuthFail)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -88,23 +75,23 @@ func (l *Lock) BeforeAuth(ctx *authboss.Context) error {
|
|||||||
// AfterAuth resets the attempt number field.
|
// AfterAuth resets the attempt number field.
|
||||||
func (l *Lock) AfterAuth(ctx *authboss.Context) {
|
func (l *Lock) AfterAuth(ctx *authboss.Context) {
|
||||||
if ctx.User == nil {
|
if ctx.User == nil {
|
||||||
fmt.Fprintln(l.logger, "lock: user not loaded in after auth callback")
|
fmt.Fprintln(authboss.Cfg.LogWriter, "lock: user not loaded in after auth callback")
|
||||||
}
|
}
|
||||||
|
|
||||||
var username string
|
var username string
|
||||||
if intf, ok := ctx.User["username"]; !ok {
|
if intf, ok := ctx.User["username"]; !ok {
|
||||||
fmt.Fprintf(l.logger, "lock: username not present")
|
fmt.Fprintf(authboss.Cfg.LogWriter, "lock: username not present")
|
||||||
return
|
return
|
||||||
} else if username, ok = intf.(string); !ok {
|
} else if username, ok = intf.(string); !ok {
|
||||||
fmt.Fprintf(l.logger, "lock: username wrong type")
|
fmt.Fprintf(authboss.Cfg.LogWriter, "lock: username wrong type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.User[UserAttemptNumber] = 0
|
ctx.User[UserAttemptNumber] = 0
|
||||||
ctx.User[UserAttemptTime] = time.Now().UTC()
|
ctx.User[UserAttemptTime] = time.Now().UTC()
|
||||||
|
|
||||||
if err := ctx.SaveUser(username, l.storer); err != nil {
|
if err := ctx.SaveUser(username, authboss.Cfg.Storer); err != nil {
|
||||||
fmt.Fprintf(l.logger, "lock: saving user failed %v", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, "lock: saving user failed %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,10 +103,10 @@ func (l *Lock) AfterAuthFail(ctx *authboss.Context) {
|
|||||||
|
|
||||||
var username string
|
var username string
|
||||||
if intf, ok := ctx.User["username"]; !ok {
|
if intf, ok := ctx.User["username"]; !ok {
|
||||||
fmt.Fprintf(l.logger, "lock: username not present")
|
fmt.Fprintf(authboss.Cfg.LogWriter, "lock: username not present")
|
||||||
return
|
return
|
||||||
} else if username, ok = intf.(string); !ok {
|
} else if username, ok = intf.(string); !ok {
|
||||||
fmt.Fprintf(l.logger, "lock: username wrong type")
|
fmt.Fprintf(authboss.Cfg.LogWriter, "lock: username wrong type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,8 +126,8 @@ func (l *Lock) AfterAuthFail(ctx *authboss.Context) {
|
|||||||
|
|
||||||
nAttempts++
|
nAttempts++
|
||||||
|
|
||||||
if time.Now().UTC().Sub(lastAttempt) <= l.window {
|
if time.Now().UTC().Sub(lastAttempt) <= authboss.Cfg.LockWindow {
|
||||||
if nAttempts >= l.attempts {
|
if nAttempts >= authboss.Cfg.LockAfter {
|
||||||
ctx.User[UserLocked] = true
|
ctx.User[UserLocked] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,8 +137,8 @@ func (l *Lock) AfterAuthFail(ctx *authboss.Context) {
|
|||||||
}
|
}
|
||||||
ctx.User[UserAttemptTime] = time.Now().UTC()
|
ctx.User[UserAttemptTime] = time.Now().UTC()
|
||||||
|
|
||||||
if err := ctx.SaveUser(username, l.storer); err != nil {
|
if err := ctx.SaveUser(username, authboss.Cfg.Storer); err != nil {
|
||||||
fmt.Fprintf(l.logger, "lock: saving user failed %v", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, "lock: saving user failed %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +173,7 @@ func (l *Lock) Unlock(key string, storer authboss.Storer) error {
|
|||||||
|
|
||||||
// Set the last attempt to be -window*2 to avoid immediately
|
// Set the last attempt to be -window*2 to avoid immediately
|
||||||
// giving another login failure.
|
// giving another login failure.
|
||||||
attr[UserAttemptTime] = time.Now().UTC().Add(-l.window * 2)
|
attr[UserAttemptTime] = time.Now().UTC().Add(-authboss.Cfg.LockWindow * 2)
|
||||||
attr[UserAttemptNumber] = 0
|
attr[UserAttemptNumber] = 0
|
||||||
attr[UserLocked] = false
|
attr[UserLocked] = false
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package lock
|
package lock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -10,6 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestStorage(t *testing.T) {
|
func TestStorage(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
storage := L.Storage()
|
storage := L.Storage()
|
||||||
if _, ok := storage[UserAttemptNumber]; !ok {
|
if _, ok := storage[UserAttemptNumber]; !ok {
|
||||||
t.Error("Expected attempt number storage option.")
|
t.Error("Expected attempt number storage option.")
|
||||||
@ -20,8 +20,8 @@ func TestStorage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBeforeAuth(t *testing.T) {
|
func TestBeforeAuth(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
ctx := authboss.NewContext()
|
ctx := authboss.NewContext()
|
||||||
L.logger = ioutil.Discard
|
|
||||||
|
|
||||||
if nil != L.BeforeAuth(ctx) {
|
if nil != L.BeforeAuth(ctx) {
|
||||||
t.Error("Expected it to break early.")
|
t.Error("Expected it to break early.")
|
||||||
@ -39,8 +39,8 @@ func TestBeforeAuth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAfterAuth(t *testing.T) {
|
func TestAfterAuth(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
lock := Lock{}
|
lock := Lock{}
|
||||||
lock.logger = ioutil.Discard
|
|
||||||
ctx := authboss.NewContext()
|
ctx := authboss.NewContext()
|
||||||
|
|
||||||
lock.AfterAuth(ctx)
|
lock.AfterAuth(ctx)
|
||||||
@ -61,7 +61,7 @@ func TestAfterAuth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
storer := mocks.NewMockStorer()
|
storer := mocks.NewMockStorer()
|
||||||
lock.storer = storer
|
authboss.Cfg.Storer = storer
|
||||||
ctx.User["username"] = "username"
|
ctx.User["username"] = "username"
|
||||||
lock.AfterAuth(ctx)
|
lock.AfterAuth(ctx)
|
||||||
|
|
||||||
@ -74,16 +74,16 @@ func TestAfterAuth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAfterAuthFail_Lock(t *testing.T) {
|
func TestAfterAuthFail_Lock(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
var old, current time.Time
|
var old, current time.Time
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
ctx := authboss.NewContext()
|
ctx := authboss.NewContext()
|
||||||
storer := mocks.NewMockStorer()
|
storer := mocks.NewMockStorer()
|
||||||
|
authboss.Cfg.Storer = storer
|
||||||
lock := Lock{}
|
lock := Lock{}
|
||||||
lock.logger = ioutil.Discard
|
authboss.Cfg.LockWindow = 30 * time.Minute
|
||||||
lock.storer = storer
|
authboss.Cfg.LockAfter = 3
|
||||||
lock.window = 30 * time.Minute
|
|
||||||
lock.attempts = 3
|
|
||||||
|
|
||||||
ctx.User = map[string]interface{}{"username": "username"}
|
ctx.User = map[string]interface{}{"username": "username"}
|
||||||
|
|
||||||
@ -117,15 +117,15 @@ func TestAfterAuthFail_Lock(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAfterAuthFail_Reset(t *testing.T) {
|
func TestAfterAuthFail_Reset(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
var old, current time.Time
|
var old, current time.Time
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
ctx := authboss.NewContext()
|
ctx := authboss.NewContext()
|
||||||
storer := mocks.NewMockStorer()
|
storer := mocks.NewMockStorer()
|
||||||
lock := Lock{}
|
lock := Lock{}
|
||||||
lock.window = 30 * time.Minute
|
authboss.Cfg.LockWindow = 30 * time.Minute
|
||||||
lock.logger = ioutil.Discard
|
authboss.Cfg.Storer = storer
|
||||||
lock.storer = storer
|
|
||||||
|
|
||||||
old = time.Now().UTC().Add(-time.Hour)
|
old = time.Now().UTC().Add(-time.Hour)
|
||||||
|
|
||||||
@ -149,8 +149,8 @@ func TestAfterAuthFail_Reset(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAfterAuthFail_Errors(t *testing.T) {
|
func TestAfterAuthFail_Errors(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
lock := Lock{}
|
lock := Lock{}
|
||||||
lock.logger = ioutil.Discard
|
|
||||||
ctx := authboss.NewContext()
|
ctx := authboss.NewContext()
|
||||||
|
|
||||||
lock.AfterAuthFail(ctx)
|
lock.AfterAuthFail(ctx)
|
||||||
@ -172,6 +172,7 @@ func TestAfterAuthFail_Errors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLock(t *testing.T) {
|
func TestLock(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
storer := mocks.NewMockStorer()
|
storer := mocks.NewMockStorer()
|
||||||
lock := Lock{}
|
lock := Lock{}
|
||||||
|
|
||||||
@ -191,9 +192,10 @@ func TestLock(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUnlock(t *testing.T) {
|
func TestUnlock(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
storer := mocks.NewMockStorer()
|
storer := mocks.NewMockStorer()
|
||||||
lock := Lock{}
|
lock := Lock{}
|
||||||
lock.window = 1 * time.Hour
|
authboss.Cfg.LockWindow = 1 * time.Hour
|
||||||
|
|
||||||
storer.Users["username"] = map[string]interface{}{
|
storer.Users["username"] = map[string]interface{}{
|
||||||
"username": "username",
|
"username": "username",
|
||||||
@ -207,7 +209,7 @@ func TestUnlock(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attemptTime := storer.Users["username"][UserAttemptTime].(time.Time)
|
attemptTime := storer.Users["username"][UserAttemptTime].(time.Time)
|
||||||
if attemptTime.After(time.Now().UTC().Add(-lock.window)) {
|
if attemptTime.After(time.Now().UTC().Add(-authboss.Cfg.LockWindow)) {
|
||||||
t.Error("UserLocked not set correctly:", attemptTime)
|
t.Error("UserLocked not set correctly:", attemptTime)
|
||||||
}
|
}
|
||||||
if number := storer.Users["username"][UserAttemptNumber].(int); number != 0 {
|
if number := storer.Users["username"][UserAttemptNumber].(int); number != 0 {
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// SendMail uses the currently configured mailer to deliver e-mails.
|
// SendMail uses the currently configured mailer to deliver e-mails.
|
||||||
func SendMail(data Email) error {
|
func SendMail(data Email) error {
|
||||||
return cfg.Mailer.Send(data)
|
return Cfg.Mailer.Send(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mailer is a type that is capable of sending an e-mail.
|
// Mailer is a type that is capable of sending an e-mail.
|
||||||
|
@ -7,12 +7,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestMailer(t *testing.T) {
|
func TestMailer(t *testing.T) {
|
||||||
|
NewConfig()
|
||||||
mailServer := &bytes.Buffer{}
|
mailServer := &bytes.Buffer{}
|
||||||
|
|
||||||
config := NewConfig()
|
Cfg.Mailer = LogMailer(mailServer)
|
||||||
config.Mailer = LogMailer(mailServer)
|
Cfg.Storer = mockStorer{}
|
||||||
config.Storer = mockStorer{}
|
Init()
|
||||||
Init(config)
|
|
||||||
|
|
||||||
err := SendMail(Email{
|
err := SendMail(Email{
|
||||||
To: []string{"some@email.com", "a@a.com"},
|
To: []string{"some@email.com", "a@a.com"},
|
||||||
|
@ -6,7 +6,7 @@ var ModuleAttrMeta = make(AttributeMeta)
|
|||||||
|
|
||||||
// Modularizer should be implemented by all the authboss modules.
|
// Modularizer should be implemented by all the authboss modules.
|
||||||
type Modularizer interface {
|
type Modularizer interface {
|
||||||
Initialize(*Config) error
|
Initialize() error
|
||||||
Routes() RouteTable
|
Routes() RouteTable
|
||||||
Storage() StorageOptions
|
Storage() StorageOptions
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
const testModName = "testmodule"
|
const testModName = "testmodule"
|
||||||
|
|
||||||
type testModule struct {
|
type testModule struct {
|
||||||
c *Config
|
|
||||||
s StorageOptions
|
s StorageOptions
|
||||||
r RouteTable
|
r RouteTable
|
||||||
}
|
}
|
||||||
@ -23,8 +22,7 @@ func testHandler(ctx *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Header().Set("testhandler", "test")
|
w.Header().Set("testhandler", "test")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testModule) Initialize(c *Config) error {
|
func (t *testModule) Initialize() error {
|
||||||
t.c = c
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,15 +24,15 @@ type pageRecoverComplete struct {
|
|||||||
func (m *RecoverModule) recoverCompleteHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r *http.Request) {
|
func (m *RecoverModule) recoverCompleteHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r *http.Request) {
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case methodGET:
|
case methodGET:
|
||||||
_, err := verifyToken(ctx, m.config.Storer.(authboss.RecoverStorer))
|
_, err := verifyToken(ctx, authboss.Cfg.Storer.(authboss.RecoverStorer))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == errRecoveryTokenExpired.Error() {
|
if err.Error() == errRecoveryTokenExpired.Error() {
|
||||||
fmt.Fprintln(m.config.LogWriter, "recover [token expired]:", err)
|
fmt.Fprintln(authboss.Cfg.LogWriter, "recover [token expired]:", err)
|
||||||
ctx.SessionStorer.Put(authboss.FlashErrorKey, m.config.RecoverTokenExpiredFlash)
|
ctx.SessionStorer.Put(authboss.FlashErrorKey, authboss.Cfg.RecoverTokenExpiredFlash)
|
||||||
http.Redirect(w, r, "/recover", http.StatusFound)
|
http.Redirect(w, r, "/recover", http.StatusFound)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintln(m.config.LogWriter, "recover:", err)
|
fmt.Fprintln(authboss.Cfg.LogWriter, "recover:", err)
|
||||||
http.Redirect(w, r, "/", http.StatusFound)
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ func (m *RecoverModule) recoverCompleteHandlerFunc(ctx *authboss.Context, w http
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, m.config.AuthLoginSuccessRoute, http.StatusFound)
|
http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound)
|
||||||
default:
|
default:
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
@ -90,24 +90,24 @@ func (m *RecoverModule) recoverComplete(ctx *authboss.Context) (errPage *pageRec
|
|||||||
token, _ := ctx.FirstFormValue("token")
|
token, _ := ctx.FirstFormValue("token")
|
||||||
password, _ := ctx.FirstPostFormValue("password")
|
password, _ := ctx.FirstPostFormValue("password")
|
||||||
confirmPassword, _ := ctx.FirstPostFormValue("confirmPassword")
|
confirmPassword, _ := ctx.FirstPostFormValue("confirmPassword")
|
||||||
defaultErrPage := &pageRecoverComplete{token, password, confirmPassword, nil, "", m.config.RecoverFailedErrorFlash}
|
defaultErrPage := &pageRecoverComplete{token, password, confirmPassword, nil, "", authboss.Cfg.RecoverFailedErrorFlash}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
ctx.User, err = verifyToken(ctx, m.config.Storer.(authboss.RecoverStorer))
|
ctx.User, err = verifyToken(ctx, authboss.Cfg.Storer.(authboss.RecoverStorer))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "failed to verify token", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "failed to verify token", err)
|
||||||
return defaultErrPage
|
return defaultErrPage
|
||||||
}
|
}
|
||||||
|
|
||||||
policies := authboss.FilterValidators(m.config.Policies, "password")
|
policies := authboss.FilterValidators(authboss.Cfg.Policies, "password")
|
||||||
if validationErrs := ctx.Validate(policies, m.config.ConfirmFields...); len(validationErrs) > 0 {
|
if validationErrs := ctx.Validate(policies, authboss.Cfg.ConfirmFields...); len(validationErrs) > 0 {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "validation failed", validationErrs)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "validation failed", validationErrs)
|
||||||
return &pageRecoverComplete{token, password, confirmPassword, validationErrs.Map(), "", ""}
|
return &pageRecoverComplete{token, password, confirmPassword, validationErrs.Map(), "", ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedPassword, err := bcrypt.GenerateFromPassword([]byte(password), m.config.BCryptCost)
|
encryptedPassword, err := bcrypt.GenerateFromPassword([]byte(password), authboss.Cfg.BCryptCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "failed to encrypt password", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "failed to encrypt password", err)
|
||||||
return defaultErrPage
|
return defaultErrPage
|
||||||
}
|
}
|
||||||
ctx.User[attrPassword] = string(encryptedPassword)
|
ctx.User[attrPassword] = string(encryptedPassword)
|
||||||
@ -116,8 +116,8 @@ func (m *RecoverModule) recoverComplete(ctx *authboss.Context) (errPage *pageRec
|
|||||||
ctx.User[attrRecoverTokenExpiry] = nullTime
|
ctx.User[attrRecoverTokenExpiry] = nullTime
|
||||||
|
|
||||||
username, _ := ctx.User.String(attrUsername)
|
username, _ := ctx.User.String(attrUsername)
|
||||||
if err := ctx.SaveUser(username, m.config.Storer); err != nil {
|
if err := ctx.SaveUser(username, authboss.Cfg.Storer); err != nil {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "failed to save user", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "failed to save user", err)
|
||||||
return defaultErrPage
|
return defaultErrPage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -22,11 +21,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Test_recoverCompleteHandlerFunc_GET_TokenExpired(t *testing.T) {
|
func Test_recoverCompleteHandlerFunc_GET_TokenExpired(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -50,7 +47,7 @@ func Test_recoverCompleteHandlerFunc_GET_TokenExpired(t *testing.T) {
|
|||||||
t.Error("Expected logs to start with:", "recover [token expired]:")
|
t.Error("Expected logs to start with:", "recover [token expired]:")
|
||||||
}
|
}
|
||||||
|
|
||||||
if flash := clientStorer.Values[authboss.FlashErrorKey]; flash != m.config.RecoverTokenExpiredFlash {
|
if flash := clientStorer.Values[authboss.FlashErrorKey]; flash != authboss.Cfg.RecoverTokenExpiredFlash {
|
||||||
t.Error("Unexpected error flash:", flash)
|
t.Error("Unexpected error flash:", flash)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +57,6 @@ func Test_recoverCompleteHandlerFunc_GET_TokenExpired(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverCompleteHandlerFunc_GET_OtherErrors(t *testing.T) {
|
func Test_recoverCompleteHandlerFunc_GET_OtherErrors(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
w, r, ctx := testHttpRequest("GET", "/recover/complete?token=asdf", nil)
|
w, r, ctx := testHttpRequest("GET", "/recover/complete?token=asdf", nil)
|
||||||
|
|
||||||
@ -81,11 +76,9 @@ func Test_recoverCompleteHandlerFunc_GET_OtherErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverCompleteHandlerFunc_GET(t *testing.T) {
|
func Test_recoverCompleteHandlerFunc_GET(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -117,8 +110,6 @@ func Test_recoverCompleteHandlerFunc_GET(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverCompleteHandlerFunc_POST_RecoveryCompleteFailed(t *testing.T) {
|
func Test_recoverCompleteHandlerFunc_POST_RecoveryCompleteFailed(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
w, r, ctx := testHttpRequest(
|
w, r, ctx := testHttpRequest(
|
||||||
"POST",
|
"POST",
|
||||||
@ -132,7 +123,7 @@ func Test_recoverCompleteHandlerFunc_POST_RecoveryCompleteFailed(t *testing.T) {
|
|||||||
Token: testUrlBase64Token,
|
Token: testUrlBase64Token,
|
||||||
Password: "a",
|
Password: "a",
|
||||||
ConfirmPassword: "a",
|
ConfirmPassword: "a",
|
||||||
FlashError: m.config.RecoverFailedErrorFlash,
|
FlashError: authboss.Cfg.RecoverFailedErrorFlash,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -140,9 +131,6 @@ func Test_recoverCompleteHandlerFunc_POST_RecoveryCompleteFailed(t *testing.T) {
|
|||||||
// missing storer will cause this to fail
|
// missing storer will cause this to fail
|
||||||
m.recoverCompleteHandlerFunc(ctx, w, r)
|
m.recoverCompleteHandlerFunc(ctx, w, r)
|
||||||
|
|
||||||
// spew.Dump(expectedBody.Bytes())
|
|
||||||
// spew.Dump(w.Body.Bytes())
|
|
||||||
|
|
||||||
if w.Code != http.StatusOK {
|
if w.Code != http.StatusOK {
|
||||||
t.Error("Unexpected code:", w.Code)
|
t.Error("Unexpected code:", w.Code)
|
||||||
}
|
}
|
||||||
@ -153,16 +141,14 @@ func Test_recoverCompleteHandlerFunc_POST_RecoveryCompleteFailed(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverCompleteHandlerFunc_POST(t *testing.T) {
|
func Test_recoverCompleteHandlerFunc_POST(t *testing.T) {
|
||||||
t.Parallel()
|
m, _ := testValidRecoverModule()
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
|
||||||
w, r, ctx := testHttpRequest(
|
w, r, ctx := testHttpRequest(
|
||||||
"POST",
|
"POST",
|
||||||
fmt.Sprintf("/recover/complete?token=%s", testUrlBase64Token),
|
fmt.Sprintf("/recover/complete?token=%s", testUrlBase64Token),
|
||||||
url.Values{"password": []string{"a"}, "confirmPassword": []string{"a"}},
|
url.Values{"password": []string{"a"}, "confirmPassword": []string{"a"}},
|
||||||
)
|
)
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -174,8 +160,6 @@ func Test_recoverCompleteHandlerFunc_POST(t *testing.T) {
|
|||||||
|
|
||||||
m.recoverCompleteHandlerFunc(ctx, w, r)
|
m.recoverCompleteHandlerFunc(ctx, w, r)
|
||||||
|
|
||||||
log.Println(logger)
|
|
||||||
|
|
||||||
if w.Code != http.StatusFound {
|
if w.Code != http.StatusFound {
|
||||||
t.Error("Unexpected code:", w.Code)
|
t.Error("Unexpected code:", w.Code)
|
||||||
}
|
}
|
||||||
@ -187,8 +171,7 @@ func Test_recoverCompleteHandlerFunc_POST(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_verifyToken_MissingToken(t *testing.T) {
|
func Test_verifyToken_MissingToken(t *testing.T) {
|
||||||
t.Parallel()
|
authboss.NewConfig()
|
||||||
|
|
||||||
ctx := mocks.MockRequestContext()
|
ctx := mocks.MockRequestContext()
|
||||||
_, err := verifyToken(ctx, nil)
|
_, err := verifyToken(ctx, nil)
|
||||||
|
|
||||||
@ -198,10 +181,9 @@ func Test_verifyToken_MissingToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_verifyToken_InvalidToken(t *testing.T) {
|
func Test_verifyToken_InvalidToken(t *testing.T) {
|
||||||
t.Parallel()
|
authboss.NewConfig()
|
||||||
|
testValidTestConfig()
|
||||||
config := testValidTestConfig()
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
storer, ok := config.Storer.(*mocks.MockStorer)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -218,10 +200,8 @@ func Test_verifyToken_InvalidToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_verifyToken_ExpiredToken(t *testing.T) {
|
func Test_verifyToken_ExpiredToken(t *testing.T) {
|
||||||
t.Parallel()
|
testValidTestConfig()
|
||||||
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
config := testValidTestConfig()
|
|
||||||
storer, ok := config.Storer.(*mocks.MockStorer)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -239,10 +219,9 @@ func Test_verifyToken_ExpiredToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_verifyToken(t *testing.T) {
|
func Test_verifyToken(t *testing.T) {
|
||||||
t.Parallel()
|
testValidTestConfig()
|
||||||
config := testValidTestConfig()
|
|
||||||
|
|
||||||
storer, ok := config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -263,8 +242,6 @@ func Test_verifyToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverComplete_TokenVerificationFails(t *testing.T) {
|
func Test_recoverComplete_TokenVerificationFails(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext()
|
ctx := mocks.MockRequestContext()
|
||||||
|
|
||||||
@ -272,7 +249,7 @@ func Test_recoverComplete_TokenVerificationFails(t *testing.T) {
|
|||||||
if errPage == nil {
|
if errPage == nil {
|
||||||
t.Error("Expected err page")
|
t.Error("Expected err page")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(*errPage, pageRecoverComplete{FlashError: m.config.RecoverFailedErrorFlash}) {
|
if !reflect.DeepEqual(*errPage, pageRecoverComplete{FlashError: authboss.Cfg.RecoverFailedErrorFlash}) {
|
||||||
t.Error("Unexpected err page:", errPage)
|
t.Error("Unexpected err page:", errPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,12 +263,10 @@ func Test_recoverComplete_TokenVerificationFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverComplete_ValidationFails(t *testing.T) {
|
func Test_recoverComplete_ValidationFails(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext("token", testUrlBase64Token, "password", "a", "confirmPassword", "b")
|
ctx := mocks.MockRequestContext("token", testUrlBase64Token, "password", "a", "confirmPassword", "b")
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -326,15 +301,13 @@ func Test_recoverComplete_ValidationFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverComplete(t *testing.T) {
|
func Test_recoverComplete(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext("token", testUrlBase64Token, "password", "a", "confirmPassword", "a")
|
ctx := mocks.MockRequestContext("token", testUrlBase64Token, "password", "a", "confirmPassword", "a")
|
||||||
|
|
||||||
clientStorer := mocks.NewMockClientStorer()
|
clientStorer := mocks.NewMockClientStorer()
|
||||||
ctx.SessionStorer = clientStorer
|
ctx.SessionStorer = clientStorer
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -375,8 +348,6 @@ func Test_recoverComplete(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverCompleteHandlerFunc_OtherMethods(t *testing.T) {
|
func Test_recoverCompleteHandlerFunc_OtherMethods(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
|
|
||||||
for i, method := range []string{"HEAD", "PUT", "DELETE", "TRACE", "CONNECT"} {
|
for i, method := range []string{"HEAD", "PUT", "DELETE", "TRACE", "CONNECT"} {
|
||||||
|
@ -35,8 +35,8 @@ func (m *RecoverModule) recoverHandlerFunc(ctx *authboss.Context, w http.Respons
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SessionStorer.Put(authboss.FlashSuccessKey, m.config.RecoverInitiateSuccessFlash)
|
ctx.SessionStorer.Put(authboss.FlashSuccessKey, authboss.Cfg.RecoverInitiateSuccessFlash)
|
||||||
http.Redirect(w, r, m.config.RecoverRedirect, http.StatusFound)
|
http.Redirect(w, r, authboss.Cfg.RecoverRedirect, http.StatusFound)
|
||||||
default:
|
default:
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
@ -46,23 +46,23 @@ func (m *RecoverModule) recover(ctx *authboss.Context) (errPage *pageRecover, em
|
|||||||
username, _ := ctx.FirstPostFormValue("username")
|
username, _ := ctx.FirstPostFormValue("username")
|
||||||
confirmUsername, _ := ctx.FirstPostFormValue("confirmUsername")
|
confirmUsername, _ := ctx.FirstPostFormValue("confirmUsername")
|
||||||
|
|
||||||
policies := authboss.FilterValidators(m.config.Policies, "username")
|
policies := authboss.FilterValidators(authboss.Cfg.Policies, "username")
|
||||||
if validationErrs := ctx.Validate(policies, m.config.ConfirmFields...); len(validationErrs) > 0 {
|
if validationErrs := ctx.Validate(policies, authboss.Cfg.ConfirmFields...); len(validationErrs) > 0 {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "validation failed", validationErrs)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "validation failed", validationErrs)
|
||||||
return &pageRecover{username, confirmUsername, validationErrs.Map(), "", ""}, nil
|
return &pageRecover{username, confirmUsername, validationErrs.Map(), "", ""}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err, emailSent := m.makeAndSendToken(ctx, username)
|
err, emailSent := m.makeAndSendToken(ctx, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "failed to recover", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "failed to recover", err)
|
||||||
return &pageRecover{username, confirmUsername, nil, "", m.config.RecoverFailedErrorFlash}, nil
|
return &pageRecover{username, confirmUsername, nil, "", authboss.Cfg.RecoverFailedErrorFlash}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, emailSent
|
return nil, emailSent
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RecoverModule) makeAndSendToken(ctx *authboss.Context, username string) (err error, emailSent <-chan struct{}) {
|
func (m *RecoverModule) makeAndSendToken(ctx *authboss.Context, username string) (err error, emailSent <-chan struct{}) {
|
||||||
if err = ctx.LoadUser(username, m.config.Storer); err != nil {
|
if err = ctx.LoadUser(username, authboss.Cfg.Storer); err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,9 +78,9 @@ func (m *RecoverModule) makeAndSendToken(ctx *authboss.Context, username string)
|
|||||||
sum := md5.Sum(token)
|
sum := md5.Sum(token)
|
||||||
|
|
||||||
ctx.User[attrRecoverToken] = base64.StdEncoding.EncodeToString(sum[:])
|
ctx.User[attrRecoverToken] = base64.StdEncoding.EncodeToString(sum[:])
|
||||||
ctx.User[attrRecoverTokenExpiry] = time.Now().Add(m.config.RecoverTokenDuration)
|
ctx.User[attrRecoverTokenExpiry] = time.Now().Add(authboss.Cfg.RecoverTokenDuration)
|
||||||
|
|
||||||
if err = ctx.SaveUser(username, m.config.Storer); err != nil {
|
if err = ctx.SaveUser(username, authboss.Cfg.Storer); err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,31 +91,31 @@ func (m *RecoverModule) sendRecoverEmail(to string, token []byte) <-chan struct{
|
|||||||
emailSent := make(chan struct{}, 1)
|
emailSent := make(chan struct{}, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
data := struct{ Link string }{fmt.Sprintf("%s/recover/complete?token=%s", m.config.HostName, base64.URLEncoding.EncodeToString(token))}
|
data := struct{ Link string }{fmt.Sprintf("%s/recover/complete?token=%s", authboss.Cfg.HostName, base64.URLEncoding.EncodeToString(token))}
|
||||||
|
|
||||||
htmlEmailBody, err := m.emailTemplates.ExecuteTemplate(tplInitHTMLEmail, data)
|
htmlEmailBody, err := m.emailTemplates.ExecuteTemplate(tplInitHTMLEmail, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "failed to build html email", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "failed to build html email", err)
|
||||||
close(emailSent)
|
close(emailSent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
textEmaiLBody, err := m.emailTemplates.ExecuteTemplate(tplInitTextEmail, data)
|
textEmaiLBody, err := m.emailTemplates.ExecuteTemplate(tplInitTextEmail, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "failed to build plaintext email", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "failed to build plaintext email", err)
|
||||||
close(emailSent)
|
close(emailSent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.config.Mailer.Send(authboss.Email{
|
if err := authboss.Cfg.Mailer.Send(authboss.Email{
|
||||||
To: []string{to},
|
To: []string{to},
|
||||||
ToNames: []string{""},
|
ToNames: []string{""},
|
||||||
From: m.config.EmailFrom,
|
From: authboss.Cfg.EmailFrom,
|
||||||
Subject: m.config.EmailSubjectPrefix + "Password Reset",
|
Subject: authboss.Cfg.EmailSubjectPrefix + "Password Reset",
|
||||||
TextBody: textEmaiLBody.String(),
|
TextBody: textEmaiLBody.String(),
|
||||||
HTMLBody: htmlEmailBody.String(),
|
HTMLBody: htmlEmailBody.String(),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "failed to send email", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "failed to send email", err)
|
||||||
close(emailSent)
|
close(emailSent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Test_recoverHandlerFunc_GET(t *testing.T) {
|
func Test_recoverHandlerFunc_GET(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
w, r, ctx := testHttpRequest("GET", "/recover", nil)
|
w, r, ctx := testHttpRequest("GET", "/recover", nil)
|
||||||
|
|
||||||
@ -36,8 +34,6 @@ func Test_recoverHandlerFunc_GET(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverHandlerFunc_POST_RecoveryFailed(t *testing.T) {
|
func Test_recoverHandlerFunc_POST_RecoveryFailed(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
w, r, ctx := testHttpRequest("POST", "/login", url.Values{"username": []string{"a"}, "confirmUsername": []string{"a"}})
|
w, r, ctx := testHttpRequest("POST", "/login", url.Values{"username": []string{"a"}, "confirmUsername": []string{"a"}})
|
||||||
|
|
||||||
@ -46,7 +42,7 @@ func Test_recoverHandlerFunc_POST_RecoveryFailed(t *testing.T) {
|
|||||||
if err := tpl.Execute(expectedBody, pageRecover{
|
if err := tpl.Execute(expectedBody, pageRecover{
|
||||||
Username: "a",
|
Username: "a",
|
||||||
ConfirmUsername: "a",
|
ConfirmUsername: "a",
|
||||||
FlashError: m.config.RecoverFailedErrorFlash,
|
FlashError: authboss.Cfg.RecoverFailedErrorFlash,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -64,12 +60,10 @@ func Test_recoverHandlerFunc_POST_RecoveryFailed(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverHandlerFunc_POST(t *testing.T) {
|
func Test_recoverHandlerFunc_POST(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
w, r, ctx := testHttpRequest("POST", "/login", url.Values{"username": []string{"a"}, "confirmUsername": []string{"a"}})
|
w, r, ctx := testHttpRequest("POST", "/login", url.Values{"username": []string{"a"}, "confirmUsername": []string{"a"}})
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -87,14 +81,12 @@ func Test_recoverHandlerFunc_POST(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
successFlash := ctx.SessionStorer.(*mocks.MockClientStorer).Values[authboss.FlashSuccessKey]
|
successFlash := ctx.SessionStorer.(*mocks.MockClientStorer).Values[authboss.FlashSuccessKey]
|
||||||
if successFlash != m.config.RecoverInitiateSuccessFlash {
|
if successFlash != authboss.Cfg.RecoverInitiateSuccessFlash {
|
||||||
t.Error("Unexpected success flash message:", successFlash)
|
t.Error("Unexpected success flash message:", successFlash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_recover_UsernameValidationFail(t *testing.T) {
|
func Test_recover_UsernameValidationFail(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext()
|
ctx := mocks.MockRequestContext()
|
||||||
|
|
||||||
@ -119,8 +111,6 @@ func Test_recover_UsernameValidationFail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recover_ConfirmUsernameCheckFail(t *testing.T) {
|
func Test_recover_ConfirmUsernameCheckFail(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext("username", "a", "confirmUsername", "b")
|
ctx := mocks.MockRequestContext("username", "a", "confirmUsername", "b")
|
||||||
|
|
||||||
@ -148,8 +138,6 @@ func Test_recover_ConfirmUsernameCheckFail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recover_InvalidUser(t *testing.T) {
|
func Test_recover_InvalidUser(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext("username", "a", "confirmUsername", "a")
|
ctx := mocks.MockRequestContext("username", "a", "confirmUsername", "a")
|
||||||
|
|
||||||
@ -157,8 +145,8 @@ func Test_recover_InvalidUser(t *testing.T) {
|
|||||||
if page.ErrMap != nil {
|
if page.ErrMap != nil {
|
||||||
t.Error("Exepted no validation errors")
|
t.Error("Exepted no validation errors")
|
||||||
}
|
}
|
||||||
if page.FlashError != m.config.RecoverFailedErrorFlash {
|
if page.FlashError != authboss.Cfg.RecoverFailedErrorFlash {
|
||||||
t.Error("Expected flash error:", m.config.RecoverFailedErrorFlash)
|
t.Error("Expected flash error:", authboss.Cfg.RecoverFailedErrorFlash)
|
||||||
}
|
}
|
||||||
|
|
||||||
actualLog, err := ioutil.ReadAll(logger)
|
actualLog, err := ioutil.ReadAll(logger)
|
||||||
@ -174,11 +162,9 @@ func Test_recover_InvalidUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recover(t *testing.T) {
|
func Test_recover(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -196,8 +182,6 @@ func Test_recover(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_makeAndSendToken_MissingStorer(t *testing.T) {
|
func Test_makeAndSendToken_MissingStorer(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext()
|
ctx := mocks.MockRequestContext()
|
||||||
|
|
||||||
@ -211,12 +195,10 @@ func Test_makeAndSendToken_MissingStorer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_makeAndSendToken_CheckEmail(t *testing.T) {
|
func Test_makeAndSendToken_CheckEmail(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext()
|
ctx := mocks.MockRequestContext()
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -244,12 +226,10 @@ func Test_makeAndSendToken_CheckEmail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_makeAndSendToken(t *testing.T) {
|
func Test_makeAndSendToken(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
ctx := mocks.MockRequestContext()
|
ctx := mocks.MockRequestContext()
|
||||||
|
|
||||||
storer, ok := m.config.Storer.(*mocks.MockStorer)
|
storer, ok := authboss.Cfg.Storer.(*mocks.MockStorer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to get storer")
|
panic("Failed to get storer")
|
||||||
}
|
}
|
||||||
@ -276,7 +256,6 @@ func Test_makeAndSendToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_sendRecoverEmail_InvalidTemplates(t *testing.T) {
|
func Test_sendRecoverEmail_InvalidTemplates(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
|
|
||||||
failTpl, err := template.New("").Parse("{{.Fail}}")
|
failTpl, err := template.New("").Parse("{{.Fail}}")
|
||||||
@ -316,12 +295,11 @@ func Test_sendRecoverEmail_InvalidTemplates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_sendRecoverEmail_FailToSend(t *testing.T) {
|
func Test_sendRecoverEmail_FailToSend(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
|
|
||||||
mailer := mocks.NewMockMailer()
|
mailer := mocks.NewMockMailer()
|
||||||
mailer.SendErr = "explode"
|
mailer.SendErr = "explode"
|
||||||
m.config.Mailer = mailer
|
authboss.Cfg.Mailer = mailer
|
||||||
<-m.sendRecoverEmail("a@b.c", []byte("abc123"))
|
<-m.sendRecoverEmail("a@b.c", []byte("abc123"))
|
||||||
|
|
||||||
actualLog, err := ioutil.ReadAll(logger)
|
actualLog, err := ioutil.ReadAll(logger)
|
||||||
@ -335,12 +313,11 @@ func Test_sendRecoverEmail_FailToSend(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_sendRecoverEmail(t *testing.T) {
|
func Test_sendRecoverEmail(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
|
|
||||||
<-m.sendRecoverEmail("a@b.c", []byte("abc123"))
|
<-m.sendRecoverEmail("a@b.c", []byte("abc123"))
|
||||||
|
|
||||||
mailer, ok := m.config.Mailer.(*mocks.MockMailer)
|
mailer, ok := authboss.Cfg.Mailer.(*mocks.MockMailer)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("Failed to assert mock mailer")
|
panic("Failed to assert mock mailer")
|
||||||
}
|
}
|
||||||
@ -353,7 +330,7 @@ func Test_sendRecoverEmail(t *testing.T) {
|
|||||||
t.Error("Unexpected to email:", sent.To[0])
|
t.Error("Unexpected to email:", sent.To[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if sent.From != m.config.EmailFrom {
|
if sent.From != authboss.Cfg.EmailFrom {
|
||||||
t.Error("Unexpected from email:", sent.From)
|
t.Error("Unexpected from email:", sent.From)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +342,7 @@ func Test_sendRecoverEmail(t *testing.T) {
|
|||||||
Link string
|
Link string
|
||||||
}{
|
}{
|
||||||
fmt.Sprintf("%s/recover/complete?token=%s",
|
fmt.Sprintf("%s/recover/complete?token=%s",
|
||||||
m.config.HostName,
|
authboss.Cfg.HostName,
|
||||||
base64.URLEncoding.EncodeToString([]byte("abc123")),
|
base64.URLEncoding.EncodeToString([]byte("abc123")),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -387,8 +364,6 @@ func Test_sendRecoverEmail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_recoverHandlerFunc_OtherMethods(t *testing.T) {
|
func Test_recoverHandlerFunc_OtherMethods(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
|
|
||||||
for i, method := range []string{"HEAD", "PUT", "DELETE", "TRACE", "CONNECT"} {
|
for i, method := range []string{"HEAD", "PUT", "DELETE", "TRACE", "CONNECT"} {
|
||||||
|
@ -37,34 +37,31 @@ func init() {
|
|||||||
type RecoverModule struct {
|
type RecoverModule struct {
|
||||||
templates views.Templates
|
templates views.Templates
|
||||||
emailTemplates views.Templates
|
emailTemplates views.Templates
|
||||||
config *authboss.Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RecoverModule) Initialize(config *authboss.Config) (err error) {
|
func (m *RecoverModule) Initialize() (err error) {
|
||||||
if config.Storer == nil {
|
if authboss.Cfg.Storer == nil {
|
||||||
return errors.New("recover: Need a RecoverStorer.")
|
return errors.New("recover: Need a RecoverStorer.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := config.Storer.(authboss.RecoverStorer); !ok {
|
if _, ok := authboss.Cfg.Storer.(authboss.RecoverStorer); !ok {
|
||||||
return errors.New("recover: RecoverStorer required for recover functionality.")
|
return errors.New("recover: RecoverStorer required for recover functionality.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Layout == nil {
|
if authboss.Cfg.Layout == nil {
|
||||||
return errors.New("recover: Layout required for Recover functionallity.")
|
return errors.New("recover: Layout required for Recover functionallity.")
|
||||||
}
|
}
|
||||||
if m.templates, err = views.Get(config.Layout, config.ViewsPath, tplRecover, tplRecoverComplete); err != nil {
|
if m.templates, err = views.Get(authboss.Cfg.Layout, authboss.Cfg.ViewsPath, tplRecover, tplRecoverComplete); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.LayoutEmail == nil {
|
if authboss.Cfg.LayoutEmail == nil {
|
||||||
return errors.New("recover: LayoutEmail required for Recover functionallity.")
|
return errors.New("recover: LayoutEmail required for Recover functionallity.")
|
||||||
}
|
}
|
||||||
if m.emailTemplates, err = views.Get(config.LayoutEmail, config.ViewsPath, tplInitHTMLEmail, tplInitTextEmail); err != nil {
|
if m.emailTemplates, err = views.Get(authboss.Cfg.LayoutEmail, authboss.Cfg.ViewsPath, tplInitHTMLEmail, tplInitTextEmail); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.config = config
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +84,7 @@ func (m *RecoverModule) Storage() authboss.StorageOptions {
|
|||||||
func (m *RecoverModule) execTpl(tpl string, w http.ResponseWriter, data interface{}) {
|
func (m *RecoverModule) execTpl(tpl string, w http.ResponseWriter, data interface{}) {
|
||||||
buffer, err := m.templates.ExecuteTemplate(tpl, data)
|
buffer, err := m.templates.ExecuteTemplate(tpl, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(m.config.LogWriter, errFormat, "unable to execute template", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, errFormat, "unable to execute template", err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -20,73 +19,73 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Test_Initialize(t *testing.T) {
|
func Test_Initialize(t *testing.T) {
|
||||||
t.Parallel()
|
authboss.NewConfig()
|
||||||
|
|
||||||
config := &authboss.Config{ViewsPath: os.TempDir()}
|
|
||||||
m := &RecoverModule{}
|
m := &RecoverModule{}
|
||||||
|
authboss.Cfg.Storer = nil
|
||||||
|
|
||||||
if err := m.Initialize(config); err == nil {
|
if err := m.Initialize(); err == nil {
|
||||||
t.Error("Expected error")
|
t.Error("Expected error")
|
||||||
} else if err.Error() != "recover: Need a RecoverStorer." {
|
} else if err.Error() != "recover: Need a RecoverStorer." {
|
||||||
t.Error("Got error but wrong reason:", err)
|
t.Error("Got error but wrong reason:", err)
|
||||||
}
|
}
|
||||||
config.Storer = mocks.MockFailStorer{}
|
authboss.Cfg.Storer = mocks.MockFailStorer{}
|
||||||
|
|
||||||
if err := m.Initialize(config); err == nil {
|
if err := m.Initialize(); err == nil {
|
||||||
t.Error("Expected error")
|
t.Error("Expected error")
|
||||||
} else if err.Error() != "recover: RecoverStorer required for recover functionality." {
|
} else if err.Error() != "recover: RecoverStorer required for recover functionality." {
|
||||||
t.Error("Got error but wrong reason:", err)
|
t.Error("Got error but wrong reason:", err)
|
||||||
}
|
}
|
||||||
config.Storer = mocks.NewMockStorer()
|
authboss.Cfg.Storer = mocks.NewMockStorer()
|
||||||
|
authboss.Cfg.Layout = nil
|
||||||
|
|
||||||
if err := m.Initialize(config); err == nil {
|
if err := m.Initialize(); err == nil {
|
||||||
t.Error("Expected error")
|
t.Error("Expected error")
|
||||||
} else if err.Error() != "recover: Layout required for Recover functionallity." {
|
} else if err.Error() != "recover: Layout required for Recover functionallity." {
|
||||||
t.Error("Got error but wrong reason:", err)
|
t.Error("Got error but wrong reason:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
config.Layout, err = template.New("").Parse(`{{template "authboss" .}}`)
|
authboss.Cfg.Layout, err = template.New("").Parse(`{{template "authboss" .}}`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unexpected error:", err)
|
t.Fatal("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
|
authboss.Cfg.LayoutEmail = nil
|
||||||
|
|
||||||
if err := m.Initialize(config); err == nil {
|
if err := m.Initialize(); err == nil {
|
||||||
t.Error("Expected error:", err)
|
t.Error("Expected error:", err)
|
||||||
} else if err.Error() != "recover: LayoutEmail required for Recover functionallity." {
|
} else if err.Error() != "recover: LayoutEmail required for Recover functionallity." {
|
||||||
t.Error("Got error but wrong reason:", err)
|
t.Error("Got error but wrong reason:", err)
|
||||||
}
|
}
|
||||||
config.LayoutEmail, err = template.New("").Parse(`{{template "authboss" .}}`)
|
authboss.Cfg.LayoutEmail, err = template.New("").Parse(`{{template "authboss" .}}`)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unexpected error:", err)
|
t.Fatal("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.Initialize(config); err != nil {
|
if err := m.Initialize(); err != nil {
|
||||||
t.Error("Unexpected error:", err)
|
t.Error("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testValidTestConfig() *authboss.Config {
|
func testValidTestConfig() {
|
||||||
config := &authboss.Config{}
|
authboss.NewConfig()
|
||||||
|
authboss.Cfg.Storer = mocks.NewMockStorer()
|
||||||
config.Storer = mocks.NewMockStorer()
|
authboss.Cfg.EmailFrom = "auth@boss.com"
|
||||||
config.EmailFrom = "auth@boss.com"
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if config.Layout, err = views.AssetToTemplate("layout.tpl"); err != nil {
|
if authboss.Cfg.Layout, err = views.AssetToTemplate("layout.tpl"); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if config.LayoutEmail, err = views.AssetToTemplate("layoutEmail.tpl"); err != nil {
|
if authboss.Cfg.LayoutEmail, err = views.AssetToTemplate("layoutEmail.tpl"); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.RecoverRedirect = "/login"
|
authboss.Cfg.RecoverRedirect = "/login"
|
||||||
config.RecoverInitiateSuccessFlash = "sf"
|
authboss.Cfg.RecoverInitiateSuccessFlash = "sf"
|
||||||
config.RecoverTokenExpiredFlash = "exf"
|
authboss.Cfg.RecoverTokenExpiredFlash = "exf"
|
||||||
config.RecoverFailedErrorFlash = "errf"
|
authboss.Cfg.RecoverFailedErrorFlash = "errf"
|
||||||
|
|
||||||
config.Policies = []authboss.Validator{
|
authboss.Cfg.Policies = []authboss.Validator{
|
||||||
authboss.Rules{
|
authboss.Rules{
|
||||||
FieldName: "username",
|
FieldName: "username",
|
||||||
Required: true,
|
Required: true,
|
||||||
@ -96,31 +95,29 @@ func testValidTestConfig() *authboss.Config {
|
|||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
config.ConfirmFields = []string{"username", "confirmUsername", "password", "confirmPassword"}
|
authboss.Cfg.ConfirmFields = []string{"username", "confirmUsername", "password", "confirmPassword"}
|
||||||
config.LogWriter = &bytes.Buffer{}
|
authboss.Cfg.LogWriter = &bytes.Buffer{}
|
||||||
config.Mailer = &mocks.MockMailer{}
|
authboss.Cfg.Mailer = &mocks.MockMailer{}
|
||||||
config.EmailFrom = "auth@boss.com"
|
authboss.Cfg.EmailFrom = "auth@boss.com"
|
||||||
config.HostName = "localhost"
|
authboss.Cfg.HostName = "localhost"
|
||||||
config.RecoverTokenDuration = time.Duration(24) * time.Hour
|
authboss.Cfg.RecoverTokenDuration = time.Duration(24) * time.Hour
|
||||||
config.BCryptCost = 4
|
authboss.Cfg.BCryptCost = 4
|
||||||
config.AuthLoginSuccessRoute = "/login"
|
authboss.Cfg.AuthLoginSuccessRoute = "/login"
|
||||||
|
|
||||||
return config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testValidRecoverModule() (*RecoverModule, *bytes.Buffer) {
|
func testValidRecoverModule() (*RecoverModule, *bytes.Buffer) {
|
||||||
c := testValidTestConfig()
|
testValidTestConfig()
|
||||||
|
|
||||||
m := &RecoverModule{}
|
m := &RecoverModule{}
|
||||||
if err := m.Initialize(c); err != nil {
|
if err := m.Initialize(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, c.LogWriter.(*bytes.Buffer)
|
return m, authboss.Cfg.LogWriter.(*bytes.Buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Routes(t *testing.T) {
|
func Test_Routes(t *testing.T) {
|
||||||
t.Parallel()
|
testValidTestConfig()
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
|
|
||||||
@ -136,7 +133,7 @@ func Test_Routes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_Storage(t *testing.T) {
|
func Test_Storage(t *testing.T) {
|
||||||
t.Parallel()
|
testValidTestConfig()
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
|
|
||||||
@ -186,7 +183,7 @@ func testHttpRequest(method, url string, data url.Values) (*httptest.ResponseRec
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_execTpl_TemplateExectionFail(t *testing.T) {
|
func Test_execTpl_TemplateExectionFail(t *testing.T) {
|
||||||
t.Parallel()
|
testValidTestConfig()
|
||||||
|
|
||||||
m, logger := testValidRecoverModule()
|
m, logger := testValidRecoverModule()
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
@ -213,12 +210,12 @@ func Test_execTpl_TemplateExectionFail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_execTpl(t *testing.T) {
|
func Test_execTpl(t *testing.T) {
|
||||||
t.Parallel()
|
testValidTestConfig()
|
||||||
|
|
||||||
m, _ := testValidRecoverModule()
|
m, _ := testValidRecoverModule()
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
page := pageRecover{"bobby", "bob", nil, "", m.config.RecoverFailedErrorFlash}
|
page := pageRecover{"bobby", "bob", nil, "", authboss.Cfg.RecoverFailedErrorFlash}
|
||||||
m.execTpl(tplRecover, w, page)
|
m.execTpl(tplRecover, w, page)
|
||||||
|
|
||||||
tpl := m.templates[tplRecover]
|
tpl := m.templates[tplRecover]
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
|
|
||||||
"gopkg.in/authboss.v0"
|
"gopkg.in/authboss.v0"
|
||||||
)
|
)
|
||||||
@ -31,26 +30,18 @@ func init() {
|
|||||||
authboss.RegisterModule("remember", R)
|
authboss.RegisterModule("remember", R)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Remember struct {
|
type Remember struct{}
|
||||||
storer authboss.TokenStorer
|
|
||||||
cookieStorer authboss.ClientStorer
|
|
||||||
sessionStorer authboss.ClientStorer
|
|
||||||
logger io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Remember) Initialize(config *authboss.Config) error {
|
func (r *Remember) Initialize() error {
|
||||||
if config.Storer == nil {
|
if authboss.Cfg.Storer == nil {
|
||||||
return errors.New("remember: Need a TokenStorer.")
|
return errors.New("remember: Need a TokenStorer.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if storer, ok := config.Storer.(authboss.TokenStorer); !ok {
|
if _, ok := authboss.Cfg.Storer.(authboss.TokenStorer); !ok {
|
||||||
return errors.New("remember: TokenStorer required for remember me functionality.")
|
return errors.New("remember: TokenStorer required for remember me functionality.")
|
||||||
} else {
|
|
||||||
r.storer = storer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r.logger = config.LogWriter
|
authboss.Cfg.Callbacks.After(authboss.EventAuth, r.AfterAuth)
|
||||||
config.Callbacks.After(authboss.EventAuth, r.AfterAuth)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -70,24 +61,24 @@ func (r *Remember) AfterAuth(ctx *authboss.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctx.User == nil {
|
if ctx.User == nil {
|
||||||
fmt.Fprintf(r.logger, "remember: AfterAuth no user loaded")
|
fmt.Fprintf(authboss.Cfg.LogWriter, "remember: AfterAuth no user loaded")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
keyIntf, ok := ctx.User["username"]
|
keyIntf, ok := ctx.User["username"]
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Fprintf(r.logger, "remember: username not present")
|
fmt.Fprintf(authboss.Cfg.LogWriter, "remember: username not present")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
key, ok := keyIntf.(string)
|
key, ok := keyIntf.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Fprintf(r.logger, "remember: username not a string")
|
fmt.Fprintf(authboss.Cfg.LogWriter, "remember: username not a string")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.New(ctx.CookieStorer, key); err != nil {
|
if _, err := r.New(ctx.CookieStorer, key); err != nil {
|
||||||
fmt.Fprintf(r.logger, "remember: Failed to create remember token: %v", err)
|
fmt.Fprintf(authboss.Cfg.LogWriter, "remember: Failed to create remember token: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +99,7 @@ func (r *Remember) New(cstorer authboss.ClientStorer, storageKey string) (string
|
|||||||
storageToken := base64.StdEncoding.EncodeToString(sum[:])
|
storageToken := base64.StdEncoding.EncodeToString(sum[:])
|
||||||
|
|
||||||
// Save the token in the DB
|
// Save the token in the DB
|
||||||
if err := r.storer.AddToken(storageKey, storageToken); err != nil {
|
if err := authboss.Cfg.Storer.(authboss.TokenStorer).AddToken(storageKey, storageToken); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +134,7 @@ func (r *Remember) Auth(
|
|||||||
// Verify the tokens match.
|
// Verify the tokens match.
|
||||||
sum := md5.Sum(token)
|
sum := md5.Sum(token)
|
||||||
|
|
||||||
key, err := r.storer.UseToken(string(givenKey), base64.StdEncoding.EncodeToString(sum[:]))
|
key, err := authboss.Cfg.Storer.(authboss.TokenStorer).UseToken(string(givenKey), base64.StdEncoding.EncodeToString(sum[:]))
|
||||||
if err == authboss.ErrTokenNotFound {
|
if err == authboss.ErrTokenNotFound {
|
||||||
return "", nil
|
return "", nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
@ -10,30 +10,32 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestInitialize(t *testing.T) {
|
func TestInitialize(t *testing.T) {
|
||||||
testConfig := authboss.NewConfig()
|
authboss.NewConfig()
|
||||||
|
|
||||||
r := &Remember{}
|
r := &Remember{}
|
||||||
err := r.Initialize(testConfig)
|
err := r.Initialize()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Expected error about token storers.")
|
t.Error("Expected error about token storers.")
|
||||||
}
|
}
|
||||||
|
|
||||||
testConfig.Storer = mocks.MockFailStorer{}
|
authboss.Cfg.Storer = mocks.MockFailStorer{}
|
||||||
err = r.Initialize(testConfig)
|
err = r.Initialize()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Expected error about token storers.")
|
t.Error("Expected error about token storers.")
|
||||||
}
|
}
|
||||||
|
|
||||||
testConfig.Storer = mocks.NewMockStorer()
|
authboss.Cfg.Storer = mocks.NewMockStorer()
|
||||||
err = r.Initialize(testConfig)
|
err = r.Initialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("Unexpected error:", err)
|
t.Error("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAfterAuth(t *testing.T) {
|
func TestAfterAuth(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
storer := mocks.NewMockStorer()
|
storer := mocks.NewMockStorer()
|
||||||
R.storer = storer
|
authboss.Cfg.Storer = storer
|
||||||
|
|
||||||
cookies := mocks.NewMockClientStorer()
|
cookies := mocks.NewMockClientStorer()
|
||||||
session := mocks.NewMockClientStorer()
|
session := mocks.NewMockClientStorer()
|
||||||
|
|
||||||
@ -60,8 +62,9 @@ func TestAfterAuth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
storer := mocks.NewMockStorer()
|
storer := mocks.NewMockStorer()
|
||||||
R.storer = storer
|
authboss.Cfg.Storer = storer
|
||||||
cookies := mocks.NewMockClientStorer()
|
cookies := mocks.NewMockClientStorer()
|
||||||
|
|
||||||
key := "tester"
|
key := "tester"
|
||||||
@ -87,8 +90,9 @@ func TestNew(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuth(t *testing.T) {
|
func TestAuth(t *testing.T) {
|
||||||
|
authboss.NewConfig()
|
||||||
storer := mocks.NewMockStorer()
|
storer := mocks.NewMockStorer()
|
||||||
R.storer = storer
|
authboss.Cfg.Storer = storer
|
||||||
cookies := mocks.NewMockClientStorer()
|
cookies := mocks.NewMockClientStorer()
|
||||||
session := mocks.NewMockClientStorer()
|
session := mocks.NewMockClientStorer()
|
||||||
|
|
||||||
|
10
router.go
10
router.go
@ -18,8 +18,8 @@ func NewRouter() http.Handler {
|
|||||||
|
|
||||||
for name, mod := range modules {
|
for name, mod := range modules {
|
||||||
for route, handler := range mod.Routes() {
|
for route, handler := range mod.Routes() {
|
||||||
fmt.Fprintf(cfg.LogWriter, "%-10s Register Route: %s\n", "["+name+"]", route)
|
fmt.Fprintf(Cfg.LogWriter, "%-10s Register Route: %s\n", "["+name+"]", route)
|
||||||
mux.Handle(path.Join(cfg.MountPath, route), contextRoute{handler})
|
mux.Handle(path.Join(Cfg.MountPath, route), contextRoute{handler})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,12 +33,12 @@ type contextRoute struct {
|
|||||||
func (c contextRoute) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (c contextRoute) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx, err := ContextFromRequest(r)
|
ctx, err := ContextFromRequest(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(cfg.LogWriter, "route: Malformed request, could not create context: %v", err)
|
fmt.Fprintf(Cfg.LogWriter, "route: Malformed request, could not create context: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.CookieStorer = cfg.CookieStoreMaker(w, r)
|
ctx.CookieStorer = Cfg.CookieStoreMaker(w, r)
|
||||||
ctx.SessionStorer = cfg.SessionStoreMaker(w, r)
|
ctx.SessionStorer = Cfg.SessionStoreMaker(w, r)
|
||||||
|
|
||||||
c.fn(ctx, w, r)
|
c.fn(ctx, w, r)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestAttributes_Names(t *testing.T) {
|
func TestAttributes_Names(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
attr := Attributes{
|
attr := Attributes{
|
||||||
"integer": 5,
|
"integer": 5,
|
||||||
"string": "string",
|
"string": "string",
|
||||||
@ -28,6 +30,8 @@ func TestAttributes_Names(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAttributeMeta_Names(t *testing.T) {
|
func TestAttributeMeta_Names(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
meta := AttributeMeta{
|
meta := AttributeMeta{
|
||||||
"integer": Integer,
|
"integer": Integer,
|
||||||
"string": String,
|
"string": String,
|
||||||
@ -49,6 +53,8 @@ func TestAttributeMeta_Names(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDataType_String(t *testing.T) {
|
func TestDataType_String(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
if Integer.String() != "Integer" {
|
if Integer.String() != "Integer" {
|
||||||
t.Error("Expected Integer:", Integer)
|
t.Error("Expected Integer:", Integer)
|
||||||
}
|
}
|
||||||
@ -64,6 +70,8 @@ func TestDataType_String(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAttributes_Bind(t *testing.T) {
|
func TestAttributes_Bind(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
anInteger := 5
|
anInteger := 5
|
||||||
aString := "string"
|
aString := "string"
|
||||||
aBool := true
|
aBool := true
|
||||||
@ -102,6 +110,8 @@ func TestAttributes_Bind(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAttributes_BindNoPtr(t *testing.T) {
|
func TestAttributes_BindNoPtr(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := Attributes{}
|
data := Attributes{}
|
||||||
s := struct{}{}
|
s := struct{}{}
|
||||||
|
|
||||||
@ -113,6 +123,8 @@ func TestAttributes_BindNoPtr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAttributes_BindMissingField(t *testing.T) {
|
func TestAttributes_BindMissingField(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := Attributes{"Integer": 5}
|
data := Attributes{"Integer": 5}
|
||||||
s := struct{}{}
|
s := struct{}{}
|
||||||
|
|
||||||
@ -124,6 +136,8 @@ func TestAttributes_BindMissingField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAttributes_BindTypeFail(t *testing.T) {
|
func TestAttributes_BindTypeFail(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Attr Attributes
|
Attr Attributes
|
||||||
Err string
|
Err string
|
||||||
@ -170,6 +184,8 @@ func TestAttributes_BindTypeFail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAttributes_Unbind(t *testing.T) {
|
func TestAttributes_Unbind(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
s1 := struct {
|
s1 := struct {
|
||||||
Integer int
|
Integer int
|
||||||
String string
|
String string
|
||||||
@ -221,6 +237,8 @@ func TestAttributes_Unbind(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCasingStyleConversions(t *testing.T) {
|
func TestCasingStyleConversions(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
camel := "SomethingInCamel"
|
camel := "SomethingInCamel"
|
||||||
|
|
||||||
got := camelToUnder(camel)
|
got := camelToUnder(camel)
|
||||||
|
@ -26,8 +26,8 @@ type Validate struct {
|
|||||||
Password authboss.Validator
|
Password authboss.Validator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Validate) Initialize(config *authboss.Config) error {
|
func (v *Validate) Initialize() error {
|
||||||
policies := authboss.FilterValidators(config.Policies, policyEmail, policyUsername, policyPassword)
|
policies := authboss.FilterValidators(authboss.Cfg.Policies, policyEmail, policyUsername, policyPassword)
|
||||||
|
|
||||||
if v.Email = policies[0]; v.Email.Field() != policyEmail {
|
if v.Email = policies[0]; v.Email.Field() != policyEmail {
|
||||||
return fmt.Errorf("validate: missin g policy: %s", policyEmail)
|
return fmt.Errorf("validate: missin g policy: %s", policyEmail)
|
||||||
@ -41,9 +41,9 @@ func (v *Validate) Initialize(config *authboss.Config) error {
|
|||||||
return fmt.Errorf("validate: missing policy: %s", policyPassword)
|
return fmt.Errorf("validate: missing policy: %s", policyPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Callbacks.Before(authboss.EventRegister, v.BeforeRegister)
|
authboss.Cfg.Callbacks.Before(authboss.EventRegister, v.BeforeRegister)
|
||||||
config.Callbacks.Before(authboss.EventRecoverStart, v.BeforeRegister)
|
authboss.Cfg.Callbacks.Before(authboss.EventRecoverStart, v.BeforeRegister)
|
||||||
config.Callbacks.Before(authboss.EventRecoverEnd, v.BeforeRegister)
|
authboss.Cfg.Callbacks.Before(authboss.EventRecoverEnd, v.BeforeRegister)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestValidate_Initialiaze(t *testing.T) {
|
func TestValidate_Initialiaze(t *testing.T) {
|
||||||
cfg := authboss.NewConfig()
|
authboss.NewConfig()
|
||||||
cfg.Policies = []authboss.Validator{
|
authboss.Cfg.Policies = []authboss.Validator{
|
||||||
authboss.Rules{FieldName: policyEmail},
|
authboss.Rules{FieldName: policyEmail},
|
||||||
authboss.Rules{FieldName: policyUsername},
|
authboss.Rules{FieldName: policyUsername},
|
||||||
authboss.Rules{FieldName: policyPassword},
|
authboss.Rules{FieldName: policyPassword},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := V.Initialize(cfg)
|
err := V.Initialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("Unexpected error:", err)
|
t.Error("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
@ -33,14 +33,14 @@ func TestValidate_Initialiaze(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidate_BeforeRegister(t *testing.T) {
|
func TestValidate_BeforeRegister(t *testing.T) {
|
||||||
cfg := authboss.NewConfig()
|
authboss.NewConfig()
|
||||||
cfg.Policies = []authboss.Validator{
|
authboss.Cfg.Policies = []authboss.Validator{
|
||||||
authboss.Rules{FieldName: policyEmail, MinLength: 15},
|
authboss.Rules{FieldName: policyEmail, MinLength: 15},
|
||||||
authboss.Rules{FieldName: policyUsername, MaxLength: 1},
|
authboss.Rules{FieldName: policyUsername, MaxLength: 1},
|
||||||
authboss.Rules{FieldName: policyPassword, MinLength: 8},
|
authboss.Rules{FieldName: policyPassword, MinLength: 8},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := V.Initialize(cfg)
|
err := V.Initialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("Unexpected error:", err)
|
t.Error("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user