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

Fix lock module.

This commit is contained in:
Aaron 2015-02-22 12:43:28 -08:00
parent 681bfdeac0
commit bab0da8575
3 changed files with 42 additions and 35 deletions

View File

@ -21,6 +21,8 @@ type MockUser struct {
ConfirmToken string
Confirmed bool
Locked bool
AttemptNumber int
AttemptTime time.Time
}
// MockStorer should be valid for any module storer defined in authboss.

View File

@ -3,7 +3,6 @@ package lock
import (
"errors"
"fmt"
"time"
"gopkg.in/authboss.v0"
@ -15,10 +14,6 @@ const (
StoreLocked = "locked"
)
var (
ErrLocked = errors.New("Account is locked.")
)
// L is the singleton instance of the lock module which will have been
// configured and ready to use after authboss.Init()
var L *Lock
@ -58,39 +53,38 @@ func (l *Lock) Storage() authboss.StorageOptions {
}
// BeforeAuth ensures the account is not locked.
func (l *Lock) BeforeAuth(ctx *authboss.Context) error {
func (l *Lock) BeforeAuth(ctx *authboss.Context) (authboss.Interrupt, error) {
if ctx.User == nil {
return errors.New("lock: user not loaded in before auth callback")
return authboss.InterruptNone, errors.New("lock: user not loaded in BeforeAuth callback")
}
if intf, ok := ctx.User[StoreLocked]; ok {
if locked, ok := intf.(bool); ok && locked {
return ErrLocked
}
if locked, ok := ctx.User.Bool(StoreLocked); ok && locked {
return authboss.InterruptAccountLocked, nil
}
return nil
return authboss.InterruptNone, nil
}
// AfterAuth resets the attempt number field.
func (l *Lock) AfterAuth(ctx *authboss.Context) {
func (l *Lock) AfterAuth(ctx *authboss.Context) error {
if ctx.User == nil {
fmt.Fprintln(authboss.Cfg.LogWriter, "lock: user not loaded in after auth callback")
return
return errors.New("lock: user not loaded in AfterAuth callback")
}
ctx.User[StoreAttemptNumber] = 0
ctx.User[StoreAttemptTime] = time.Now().UTC()
if err := ctx.SaveUser(); err != nil {
fmt.Fprintf(authboss.Cfg.LogWriter, "lock: saving user failed %v", err)
return err
}
return nil
}
// AfterAuthFail adjusts the attempt number and time.
func (l *Lock) AfterAuthFail(ctx *authboss.Context) {
func (l *Lock) AfterAuthFail(ctx *authboss.Context) error {
if ctx.User == nil {
return
return errors.New("lock: user not loaded in AfterAuth callback")
}
lastAttempt := time.Now().UTC()
@ -117,13 +111,15 @@ func (l *Lock) AfterAuthFail(ctx *authboss.Context) {
ctx.User[StoreAttemptTime] = time.Now().UTC()
if err := ctx.SaveUser(); err != nil {
fmt.Fprintf(authboss.Cfg.LogWriter, "lock: saving user failed %v", err)
return err
}
return nil
}
// Lock a user manually.
func (l *Lock) Lock(key string, storer authboss.Storer) error {
user, err := storer.Get(key, authboss.ModuleAttrMeta)
func (l *Lock) Lock(key string) error {
user, err := authboss.Cfg.Storer.Get(key, authboss.ModuleAttrMeta)
if err != nil {
return err
}
@ -135,12 +131,12 @@ func (l *Lock) Lock(key string, storer authboss.Storer) error {
attr[StoreLocked] = true
return storer.Put(key, attr)
return authboss.Cfg.Storer.Put(key, attr)
}
// Unlock a user that was locked by this module.
func (l *Lock) Unlock(key string, storer authboss.Storer) error {
user, err := storer.Get(key, authboss.ModuleAttrMeta)
func (l *Lock) Unlock(key string) error {
user, err := authboss.Cfg.Storer.Get(key, authboss.ModuleAttrMeta)
if err != nil {
return err
}
@ -156,5 +152,5 @@ func (l *Lock) Unlock(key string, storer authboss.Storer) error {
attr[StoreAttemptNumber] = 0
attr[StoreLocked] = false
return storer.Put(key, attr)
return authboss.Cfg.Storer.Put(key, attr)
}

View File

@ -23,14 +23,18 @@ func TestBeforeAuth(t *testing.T) {
authboss.NewConfig()
ctx := authboss.NewContext()
if err := L.BeforeAuth(ctx); err == nil {
if interrupt, err := L.BeforeAuth(ctx); err == nil {
t.Error("Want death because user not loaded:", err)
} else if interrupt != authboss.InterruptNone {
t.Error("Interrupt should not be set:", interrupt)
}
ctx.User = authboss.Attributes{"locked": true}
if err := L.BeforeAuth(ctx); err != ErrLocked {
t.Error("Expected an ErrLocked:", err)
if interrupt, err := L.BeforeAuth(ctx); err != nil {
t.Error(err)
} else if interrupt != authboss.InterruptAccountLocked {
t.Error("Expected a locked interrupt:", interrupt)
}
}
@ -39,16 +43,17 @@ func TestAfterAuth(t *testing.T) {
lock := Lock{}
ctx := authboss.NewContext()
lock.AfterAuth(ctx)
if _, ok := ctx.User[StoreAttemptNumber]; ok {
t.Error("Expected nothing to be set, missing user.")
if err := lock.AfterAuth(ctx); err == nil {
t.Error("Expected an error because of missing user.")
}
storer := mocks.NewMockStorer()
authboss.Cfg.Storer = storer
ctx.User = authboss.Attributes{"username": "username"}
lock.AfterAuth(ctx)
if err := lock.AfterAuth(ctx); err != nil {
t.Error(err)
}
if storer.Users["username"][StoreAttemptNumber].(int) != 0 {
t.Error("StoreAttemptNumber set incorrectly.")
}
@ -78,7 +83,9 @@ func TestAfterAuthFail_Lock(t *testing.T) {
t.Errorf("%d: User should not be locked.", i)
}
lock.AfterAuthFail(ctx)
if err := lock.AfterAuthFail(ctx); err != nil {
t.Error(err)
}
if val := storer.Users["username"][StoreAttemptNumber].(int); val != i+1 {
t.Errorf("%d: StoreAttemptNumber set incorrectly: %v", i, val)
}
@ -146,6 +153,7 @@ func TestAfterAuthFail_Errors(t *testing.T) {
func TestLock(t *testing.T) {
authboss.NewConfig()
storer := mocks.NewMockStorer()
authboss.Cfg.Storer = storer
lock := Lock{}
storer.Users["username"] = map[string]interface{}{
@ -153,7 +161,7 @@ func TestLock(t *testing.T) {
"password": "password",
}
err := lock.Lock("username", storer)
err := lock.Lock("username")
if err != nil {
t.Error(err)
}
@ -166,6 +174,7 @@ func TestLock(t *testing.T) {
func TestUnlock(t *testing.T) {
authboss.NewConfig()
storer := mocks.NewMockStorer()
authboss.Cfg.Storer = storer
lock := Lock{}
authboss.Cfg.LockWindow = 1 * time.Hour
@ -175,7 +184,7 @@ func TestUnlock(t *testing.T) {
"locked": true,
}
err := lock.Unlock("username", storer)
err := lock.Unlock("username")
if err != nil {
t.Error(err)
}