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:
parent
681bfdeac0
commit
bab0da8575
@ -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.
|
||||
|
46
lock/lock.go
46
lock/lock.go
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user