2015-01-24 02:25:12 +02:00
|
|
|
package lock
|
|
|
|
|
2015-01-25 08:19:22 +02:00
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"gopkg.in/authboss.v0"
|
|
|
|
"gopkg.in/authboss.v0/internal/mocks"
|
|
|
|
)
|
2015-01-24 02:25:12 +02:00
|
|
|
|
|
|
|
func TestStorage(t *testing.T) {
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.NewConfig()
|
2015-01-24 02:25:12 +02:00
|
|
|
storage := L.Storage()
|
|
|
|
if _, ok := storage[UserAttemptNumber]; !ok {
|
|
|
|
t.Error("Expected attempt number storage option.")
|
|
|
|
}
|
|
|
|
if _, ok := storage[UserAttemptTime]; !ok {
|
|
|
|
t.Error("Expected attempt number time option.")
|
|
|
|
}
|
|
|
|
}
|
2015-01-25 08:19:22 +02:00
|
|
|
|
|
|
|
func TestBeforeAuth(t *testing.T) {
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.NewConfig()
|
2015-01-25 08:19:22 +02:00
|
|
|
ctx := authboss.NewContext()
|
|
|
|
|
2015-02-16 21:32:31 +02:00
|
|
|
if err := L.BeforeAuth(ctx); err == nil {
|
|
|
|
t.Error("Want death because user not loaded:", err)
|
2015-01-25 08:19:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ctx.User = authboss.Attributes{"locked": true}
|
|
|
|
|
|
|
|
if err := L.BeforeAuth(ctx); err != ErrLocked {
|
|
|
|
t.Error("Expected an ErrLocked:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAfterAuth(t *testing.T) {
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.NewConfig()
|
2015-01-25 08:19:22 +02:00
|
|
|
lock := Lock{}
|
|
|
|
ctx := authboss.NewContext()
|
|
|
|
|
|
|
|
lock.AfterAuth(ctx)
|
|
|
|
if _, ok := ctx.User[UserAttemptNumber]; ok {
|
|
|
|
t.Error("Expected nothing to be set, missing user.")
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.User = map[string]interface{}{"otherattribute": "somevalue"}
|
|
|
|
lock.AfterAuth(ctx)
|
|
|
|
if _, ok := ctx.User[UserAttemptNumber]; ok {
|
|
|
|
t.Error("Expected username not present to stop this assignment.")
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.User["username"] = 5
|
|
|
|
lock.AfterAuth(ctx)
|
|
|
|
if _, ok := ctx.User[UserAttemptNumber]; ok {
|
|
|
|
t.Error("Expected username wrong type stop this assignment.")
|
|
|
|
}
|
|
|
|
|
|
|
|
storer := mocks.NewMockStorer()
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.Cfg.Storer = storer
|
2015-01-25 08:19:22 +02:00
|
|
|
ctx.User["username"] = "username"
|
|
|
|
lock.AfterAuth(ctx)
|
|
|
|
|
|
|
|
if storer.Users["username"][UserAttemptNumber].(int) != 0 {
|
|
|
|
t.Error("UserAttemptNumber set incorrectly.")
|
|
|
|
}
|
|
|
|
if _, ok := storer.Users["username"][UserAttemptTime].(time.Time); !ok {
|
|
|
|
t.Error("UserAttemptTime not set.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAfterAuthFail_Lock(t *testing.T) {
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.NewConfig()
|
2015-01-25 08:19:22 +02:00
|
|
|
var old, current time.Time
|
|
|
|
var ok bool
|
|
|
|
|
|
|
|
ctx := authboss.NewContext()
|
|
|
|
storer := mocks.NewMockStorer()
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.Cfg.Storer = storer
|
2015-01-25 08:19:22 +02:00
|
|
|
lock := Lock{}
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.Cfg.LockWindow = 30 * time.Minute
|
|
|
|
authboss.Cfg.LockAfter = 3
|
2015-01-25 08:19:22 +02:00
|
|
|
|
|
|
|
ctx.User = map[string]interface{}{"username": "username"}
|
|
|
|
|
|
|
|
old = time.Now().UTC().Add(-1 * time.Hour)
|
|
|
|
|
|
|
|
for i := 0; i < 3; i++ {
|
|
|
|
if lockedIntf, ok := storer.Users["username"][UserLocked]; ok && lockedIntf.(bool) {
|
|
|
|
t.Errorf("%d: User should not be locked.", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
lock.AfterAuthFail(ctx)
|
|
|
|
if val := storer.Users["username"][UserAttemptNumber].(int); val != i+1 {
|
|
|
|
t.Errorf("%d: UserAttemptNumber set incorrectly: %v", i, val)
|
|
|
|
}
|
|
|
|
if current, ok = storer.Users["username"][UserAttemptTime].(time.Time); !ok || old.After(current) {
|
|
|
|
t.Error("%d: UserAttemptTime not set correctly: %v", i, current)
|
|
|
|
}
|
|
|
|
|
|
|
|
current = old
|
|
|
|
}
|
|
|
|
|
|
|
|
if !storer.Users["username"][UserLocked].(bool) {
|
|
|
|
t.Error("User should be locked.")
|
|
|
|
}
|
|
|
|
if val := storer.Users["username"][UserAttemptNumber].(int); val != 3 {
|
|
|
|
t.Error("UserAttemptNumber set incorrectly:", val)
|
|
|
|
}
|
|
|
|
if _, ok = storer.Users["username"][UserAttemptTime].(time.Time); !ok {
|
|
|
|
t.Error("UserAttemptTime not set correctly.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAfterAuthFail_Reset(t *testing.T) {
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.NewConfig()
|
2015-01-25 08:19:22 +02:00
|
|
|
var old, current time.Time
|
|
|
|
var ok bool
|
|
|
|
|
|
|
|
ctx := authboss.NewContext()
|
|
|
|
storer := mocks.NewMockStorer()
|
|
|
|
lock := Lock{}
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.Cfg.LockWindow = 30 * time.Minute
|
|
|
|
authboss.Cfg.Storer = storer
|
2015-01-25 08:19:22 +02:00
|
|
|
|
|
|
|
old = time.Now().UTC().Add(-time.Hour)
|
|
|
|
|
|
|
|
ctx.User = map[string]interface{}{
|
|
|
|
"username": "username",
|
|
|
|
UserAttemptNumber: 2,
|
|
|
|
UserAttemptTime: old,
|
|
|
|
UserLocked: false,
|
|
|
|
}
|
|
|
|
|
|
|
|
lock.AfterAuthFail(ctx)
|
|
|
|
if val := storer.Users["username"][UserAttemptNumber].(int); val != 0 {
|
|
|
|
t.Error("UserAttemptNumber set incorrectly:", val)
|
|
|
|
}
|
|
|
|
if current, ok = storer.Users["username"][UserAttemptTime].(time.Time); !ok || current.Before(old) {
|
|
|
|
t.Error("UserAttemptTime not set correctly.")
|
|
|
|
}
|
|
|
|
if locked := storer.Users["username"][UserLocked].(bool); locked {
|
|
|
|
t.Error("UserLocked not set correctly:", locked)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAfterAuthFail_Errors(t *testing.T) {
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.NewConfig()
|
2015-01-25 08:19:22 +02:00
|
|
|
lock := Lock{}
|
|
|
|
ctx := authboss.NewContext()
|
|
|
|
|
|
|
|
lock.AfterAuthFail(ctx)
|
|
|
|
if _, ok := ctx.User[UserAttemptNumber]; ok {
|
|
|
|
t.Error("Expected nothing to be set, missing user.")
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.User = map[string]interface{}{"otherattribute": "somevalue"}
|
|
|
|
lock.AfterAuthFail(ctx)
|
|
|
|
if _, ok := ctx.User[UserAttemptNumber]; ok {
|
|
|
|
t.Error("Expected username not present to stop this assignment.")
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.User["username"] = 5
|
|
|
|
lock.AfterAuthFail(ctx)
|
|
|
|
if _, ok := ctx.User[UserAttemptNumber]; ok {
|
|
|
|
t.Error("Expected username wrong type stop this assignment.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLock(t *testing.T) {
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.NewConfig()
|
2015-01-25 08:19:22 +02:00
|
|
|
storer := mocks.NewMockStorer()
|
|
|
|
lock := Lock{}
|
|
|
|
|
|
|
|
storer.Users["username"] = map[string]interface{}{
|
|
|
|
"username": "username",
|
|
|
|
"password": "password",
|
|
|
|
}
|
|
|
|
|
|
|
|
err := lock.Lock("username", storer)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if locked := storer.Users["username"][UserLocked].(bool); !locked {
|
|
|
|
t.Error("User should be locked.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnlock(t *testing.T) {
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.NewConfig()
|
2015-01-25 08:19:22 +02:00
|
|
|
storer := mocks.NewMockStorer()
|
|
|
|
lock := Lock{}
|
2015-02-16 06:07:36 +02:00
|
|
|
authboss.Cfg.LockWindow = 1 * time.Hour
|
2015-01-25 08:19:22 +02:00
|
|
|
|
|
|
|
storer.Users["username"] = map[string]interface{}{
|
|
|
|
"username": "username",
|
|
|
|
"password": "password",
|
|
|
|
"locked": true,
|
|
|
|
}
|
|
|
|
|
|
|
|
err := lock.Unlock("username", storer)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
attemptTime := storer.Users["username"][UserAttemptTime].(time.Time)
|
2015-02-16 06:07:36 +02:00
|
|
|
if attemptTime.After(time.Now().UTC().Add(-authboss.Cfg.LockWindow)) {
|
2015-01-25 08:19:22 +02:00
|
|
|
t.Error("UserLocked not set correctly:", attemptTime)
|
|
|
|
}
|
|
|
|
if number := storer.Users["username"][UserAttemptNumber].(int); number != 0 {
|
|
|
|
t.Error("UserLocked not set correctly:", number)
|
|
|
|
}
|
|
|
|
if locked := storer.Users["username"][UserLocked].(bool); locked {
|
|
|
|
t.Error("User should not be locked.")
|
|
|
|
}
|
|
|
|
}
|