mirror of
https://github.com/volatiletech/authboss.git
synced 2024-11-28 08:58:38 +02:00
parent
4eeb21e16d
commit
001810bf7c
25
auth/auth.go
25
auth/auth.go
@ -14,9 +14,6 @@ const (
|
||||
methodPOST = "POST"
|
||||
|
||||
tplLogin = "login.tpl"
|
||||
|
||||
storeUsername = "username"
|
||||
storePassword = "password"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -37,7 +34,7 @@ func (a *AuthModule) Initialize() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
a.policies = authboss.FilterValidators(authboss.Cfg.Policies, "username", "password")
|
||||
a.policies = authboss.FilterValidators(authboss.Cfg.Policies, authboss.Cfg.PrimaryID, authboss.StorePassword)
|
||||
|
||||
a.isRememberLoaded = authboss.IsLoaded("remember")
|
||||
a.isRecoverLoaded = authboss.IsLoaded("recover")
|
||||
@ -54,8 +51,8 @@ func (a *AuthModule) Routes() authboss.RouteTable {
|
||||
|
||||
func (a *AuthModule) Storage() authboss.StorageOptions {
|
||||
return authboss.StorageOptions{
|
||||
storeUsername: authboss.String,
|
||||
storePassword: authboss.String,
|
||||
authboss.Cfg.PrimaryID: authboss.String,
|
||||
authboss.StorePassword: authboss.String,
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +60,7 @@ func (a *AuthModule) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWrit
|
||||
switch r.Method {
|
||||
case methodGET:
|
||||
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.SessionHalfAuthKey); !ok || halfAuthed == "false" {
|
||||
http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound)
|
||||
}
|
||||
}
|
||||
@ -86,12 +83,12 @@ func (a *AuthModule) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWrit
|
||||
return nil
|
||||
}
|
||||
|
||||
username, _ := ctx.FirstPostFormValue("username")
|
||||
key, _ := ctx.FirstPostFormValue(authboss.Cfg.PrimaryID)
|
||||
password, _ := ctx.FirstPostFormValue("password")
|
||||
|
||||
errData := authboss.NewHTMLData(
|
||||
"error", "invalid username and/or password",
|
||||
"username", username,
|
||||
authboss.Cfg.PrimaryID, key,
|
||||
"showRemember", a.isRememberLoaded,
|
||||
"showRecover", a.isRecoverLoaded,
|
||||
)
|
||||
@ -101,12 +98,12 @@ func (a *AuthModule) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWrit
|
||||
return a.templates.Render(ctx, w, r, tplLogin, errData)
|
||||
}
|
||||
|
||||
if err := validateCredentials(ctx, username, password); err != nil {
|
||||
if err := validateCredentials(ctx, key, password); err != nil {
|
||||
fmt.Fprintln(authboss.Cfg.LogWriter, "auth: failed to validate credentials:", err)
|
||||
return a.templates.Render(ctx, w, r, tplLogin, errData)
|
||||
}
|
||||
|
||||
ctx.SessionStorer.Put(authboss.SessionKey, username)
|
||||
ctx.SessionStorer.Put(authboss.SessionKey, key)
|
||||
authboss.Cfg.Callbacks.FireAfter(authboss.EventAuth, ctx)
|
||||
http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound)
|
||||
default:
|
||||
@ -116,12 +113,12 @@ func (a *AuthModule) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWrit
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateCredentials(ctx *authboss.Context, username, password string) error {
|
||||
if err := ctx.LoadUser(username); err != nil {
|
||||
func validateCredentials(ctx *authboss.Context, key, password string) error {
|
||||
if err := ctx.LoadUser(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
actualPassword, err := ctx.User.StringErr(storePassword)
|
||||
actualPassword, err := ctx.User.StringErr(authboss.StorePassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ const (
|
||||
// HalfAuthKey is used for sessions that have been authenticated by
|
||||
// the remember module. This serves as a way to force full authentication
|
||||
// by denying half-authed users acccess to sensitive areas.
|
||||
HalfAuthKey = "halfauth"
|
||||
SessionHalfAuthKey = "halfauth"
|
||||
// FlashSuccessKey is used for storing sucess flash messages on the session
|
||||
FlashSuccessKey = "flash_success"
|
||||
// FlashErrorKey is used for storing sucess flash messages on the session
|
||||
|
23
config.go
23
config.go
@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@ -20,15 +21,19 @@ var Cfg *Config = NewConfig()
|
||||
|
||||
// Config holds all the configuration for both authboss and it's modules.
|
||||
type Config struct {
|
||||
// MountPath is the path to mount the router at.
|
||||
// MountPath is the path to mount authboss's routes at (eg /auth).
|
||||
MountPath string
|
||||
// ViewsPath is the path to overiding view template files.
|
||||
// ViewsPath is the path to search for overridden templates.
|
||||
ViewsPath string
|
||||
// HostName is self explanitory
|
||||
// HostName is the host of the web application (eg https://www.happiness.com:8080) for e-mail url generation.
|
||||
HostName string
|
||||
// BCryptPasswordCost is self explanitory.
|
||||
// BCryptCost is the cost of the bcrypt password hashing function.
|
||||
BCryptCost int
|
||||
|
||||
// PrimaryID is the primary identifier of the user. Set to one of:
|
||||
// authboss.StoreEmail, authboss.StoreUsername (StoreEmail is default)
|
||||
PrimaryID string
|
||||
|
||||
Layout *template.Template
|
||||
LayoutEmail *template.Template
|
||||
LayoutDataMaker ViewDataMaker
|
||||
@ -45,7 +50,8 @@ type Config struct {
|
||||
Policies []Validator
|
||||
ConfirmFields []string
|
||||
|
||||
ExpireAfter time.Duration
|
||||
ExpireAfter time.Duration
|
||||
|
||||
LockAfter int
|
||||
LockWindow time.Duration
|
||||
LockDuration time.Duration
|
||||
@ -73,6 +79,8 @@ func NewConfig() *Config {
|
||||
HostName: "localhost:8080",
|
||||
BCryptCost: bcrypt.DefaultCost,
|
||||
|
||||
PrimaryID: StoreEmail,
|
||||
|
||||
Layout: template.Must(template.New("").Parse(`<html><body>{{template "authboss" .}}</body></html>`)),
|
||||
LayoutEmail: template.Must(template.New("").Parse(`<html><body>{{template "authboss" .}}</body></html>`)),
|
||||
|
||||
@ -96,7 +104,10 @@ func NewConfig() *Config {
|
||||
AllowWhitespace: false,
|
||||
},
|
||||
},
|
||||
ConfirmFields: []string{"username", "confirmUsername", "password", "confirmPassword"},
|
||||
ConfirmFields: []string{
|
||||
StoreEmail, "confirm" + strings.Title(StoreEmail),
|
||||
StorePassword, "confirm" + strings.Title(StorePassword),
|
||||
},
|
||||
|
||||
RecoverRedirect: "/login",
|
||||
RecoverInitiateSuccessFlash: "An email has been sent with further insructions on how to reset your password",
|
||||
|
@ -98,6 +98,7 @@ func TestConfirm_AfterRegister(t *testing.T) {
|
||||
log := &bytes.Buffer{}
|
||||
authboss.Cfg.LogWriter = log
|
||||
authboss.Cfg.Mailer = authboss.LogMailer(log)
|
||||
authboss.Cfg.PrimaryID = authboss.StoreUsername
|
||||
|
||||
sentEmail := false
|
||||
|
||||
@ -110,7 +111,7 @@ func TestConfirm_AfterRegister(t *testing.T) {
|
||||
t.Error("Expected it to die with user error:", err)
|
||||
}
|
||||
|
||||
ctx.User = authboss.Attributes{authboss.StoreUsername: "uname"}
|
||||
ctx.User = authboss.Attributes{authboss.Cfg.PrimaryID: "username"}
|
||||
if err := c.AfterRegister(ctx); err == nil || err.(authboss.AttributeErr).Name != "email" {
|
||||
t.Error("Expected it to die with e-mail address error:", err)
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ func (c *Context) SaveUser() error {
|
||||
return errors.New("User not initialized.")
|
||||
}
|
||||
|
||||
key, ok := c.User.String("username")
|
||||
key, ok := c.User.String(Cfg.PrimaryID)
|
||||
if !ok {
|
||||
return errors.New("User improperly initialized, primary ID missing")
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ func TestContext_SaveUser(t *testing.T) {
|
||||
ctx := NewContext()
|
||||
storer := mockStorer{}
|
||||
Cfg.Storer = storer
|
||||
ctx.User = Attributes{"username": "joe", "email": "hello@joe.com", "password": "mysticalhash"}
|
||||
ctx.User = Attributes{StoreUsername: "joe", StoreEmail: "hello@joe.com", StorePassword: "mysticalhash"}
|
||||
|
||||
err := ctx.SaveUser()
|
||||
if err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
attr, ok := storer["joe"]
|
||||
attr, ok := storer["hello@joe.com"]
|
||||
if !ok {
|
||||
t.Error("Could not find joe!")
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ func TestExpire_Middleware(t *testing.T) {
|
||||
authboss.NewConfig()
|
||||
session := mocks.NewMockClientStorer()
|
||||
session.Values = map[string]string{
|
||||
authboss.SessionKey: "username",
|
||||
authboss.SessionKey: "email@email.com",
|
||||
}
|
||||
maker := func(w http.ResponseWriter, r *http.Request) authboss.ClientStorer { return session }
|
||||
|
||||
|
@ -49,15 +49,15 @@ func TestAfterAuth(t *testing.T) {
|
||||
|
||||
storer := mocks.NewMockStorer()
|
||||
authboss.Cfg.Storer = storer
|
||||
ctx.User = authboss.Attributes{"username": "username"}
|
||||
ctx.User = authboss.Attributes{authboss.Cfg.PrimaryID: "john@john.com"}
|
||||
|
||||
if err := lock.AfterAuth(ctx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if storer.Users["username"][StoreAttemptNumber].(int) != 0 {
|
||||
if storer.Users["john@john.com"][StoreAttemptNumber].(int) != 0 {
|
||||
t.Error("StoreAttemptNumber set incorrectly.")
|
||||
}
|
||||
if _, ok := storer.Users["username"][StoreAttemptTime].(time.Time); !ok {
|
||||
if _, ok := storer.Users["john@john.com"][StoreAttemptTime].(time.Time); !ok {
|
||||
t.Error("StoreAttemptTime not set.")
|
||||
}
|
||||
}
|
||||
@ -74,35 +74,37 @@ func TestAfterAuthFail_Lock(t *testing.T) {
|
||||
authboss.Cfg.LockWindow = 30 * time.Minute
|
||||
authboss.Cfg.LockAfter = 3
|
||||
|
||||
ctx.User = map[string]interface{}{"username": "username"}
|
||||
email := "john@john.com"
|
||||
|
||||
ctx.User = map[string]interface{}{authboss.Cfg.PrimaryID: email}
|
||||
|
||||
old = time.Now().UTC().Add(-1 * time.Hour)
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
if lockedIntf, ok := storer.Users["username"][StoreLocked]; ok && lockedIntf.(bool) {
|
||||
if lockedIntf, ok := storer.Users["john@john.com"][StoreLocked]; ok && lockedIntf.(bool) {
|
||||
t.Errorf("%d: User should not be locked.", i)
|
||||
}
|
||||
|
||||
if err := lock.AfterAuthFail(ctx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if val := storer.Users["username"][StoreAttemptNumber].(int); val != i+1 {
|
||||
if val := storer.Users[email][StoreAttemptNumber].(int); val != i+1 {
|
||||
t.Errorf("%d: StoreAttemptNumber set incorrectly: %v", i, val)
|
||||
}
|
||||
if current, ok = storer.Users["username"][StoreAttemptTime].(time.Time); !ok || old.After(current) {
|
||||
if current, ok = storer.Users[email][StoreAttemptTime].(time.Time); !ok || old.After(current) {
|
||||
t.Error("%d: StoreAttemptTime not set correctly: %v", i, current)
|
||||
}
|
||||
|
||||
current = old
|
||||
}
|
||||
|
||||
if !storer.Users["username"][StoreLocked].(bool) {
|
||||
if !storer.Users[email][StoreLocked].(bool) {
|
||||
t.Error("User should be locked.")
|
||||
}
|
||||
if val := storer.Users["username"][StoreAttemptNumber].(int); val != 3 {
|
||||
if val := storer.Users[email][StoreAttemptNumber].(int); val != 3 {
|
||||
t.Error("StoreAttemptNumber set incorrectly:", val)
|
||||
}
|
||||
if _, ok = storer.Users["username"][StoreAttemptTime].(time.Time); !ok {
|
||||
if _, ok = storer.Users[email][StoreAttemptTime].(time.Time); !ok {
|
||||
t.Error("StoreAttemptTime not set correctly.")
|
||||
}
|
||||
}
|
||||
@ -120,21 +122,22 @@ func TestAfterAuthFail_Reset(t *testing.T) {
|
||||
|
||||
old = time.Now().UTC().Add(-time.Hour)
|
||||
|
||||
email := "john@john.com"
|
||||
ctx.User = map[string]interface{}{
|
||||
"username": "username",
|
||||
StoreAttemptNumber: 2,
|
||||
StoreAttemptTime: old,
|
||||
StoreLocked: false,
|
||||
authboss.Cfg.PrimaryID: email,
|
||||
StoreAttemptNumber: 2,
|
||||
StoreAttemptTime: old,
|
||||
StoreLocked: false,
|
||||
}
|
||||
|
||||
lock.AfterAuthFail(ctx)
|
||||
if val := storer.Users["username"][StoreAttemptNumber].(int); val != 0 {
|
||||
if val := storer.Users[email][StoreAttemptNumber].(int); val != 0 {
|
||||
t.Error("StoreAttemptNumber set incorrectly:", val)
|
||||
}
|
||||
if current, ok = storer.Users["username"][StoreAttemptTime].(time.Time); !ok || current.Before(old) {
|
||||
if current, ok = storer.Users[email][StoreAttemptTime].(time.Time); !ok || current.Before(old) {
|
||||
t.Error("StoreAttemptTime not set correctly.")
|
||||
}
|
||||
if locked := storer.Users["username"][StoreLocked].(bool); locked {
|
||||
if locked := storer.Users[email][StoreLocked].(bool); locked {
|
||||
t.Error("StoreLocked not set correctly:", locked)
|
||||
}
|
||||
}
|
||||
@ -156,17 +159,18 @@ func TestLock(t *testing.T) {
|
||||
authboss.Cfg.Storer = storer
|
||||
lock := Lock{}
|
||||
|
||||
storer.Users["username"] = map[string]interface{}{
|
||||
"username": "username",
|
||||
"password": "password",
|
||||
email := "john@john.com"
|
||||
storer.Users[email] = map[string]interface{}{
|
||||
authboss.Cfg.PrimaryID: email,
|
||||
"password": "password",
|
||||
}
|
||||
|
||||
err := lock.Lock("username")
|
||||
err := lock.Lock(email)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if locked := storer.Users["username"][StoreLocked].(bool); !locked {
|
||||
if locked := storer.Users[email][StoreLocked].(bool); !locked {
|
||||
t.Error("User should be locked.")
|
||||
}
|
||||
}
|
||||
@ -178,25 +182,26 @@ func TestUnlock(t *testing.T) {
|
||||
lock := Lock{}
|
||||
authboss.Cfg.LockWindow = 1 * time.Hour
|
||||
|
||||
storer.Users["username"] = map[string]interface{}{
|
||||
"username": "username",
|
||||
"password": "password",
|
||||
"locked": true,
|
||||
email := "john@john.com"
|
||||
storer.Users[email] = map[string]interface{}{
|
||||
authboss.Cfg.PrimaryID: email,
|
||||
"password": "password",
|
||||
"locked": true,
|
||||
}
|
||||
|
||||
err := lock.Unlock("username")
|
||||
err := lock.Unlock(email)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
attemptTime := storer.Users["username"][StoreAttemptTime].(time.Time)
|
||||
attemptTime := storer.Users[email][StoreAttemptTime].(time.Time)
|
||||
if attemptTime.After(time.Now().UTC().Add(-authboss.Cfg.LockWindow)) {
|
||||
t.Error("StoreLocked not set correctly:", attemptTime)
|
||||
}
|
||||
if number := storer.Users["username"][StoreAttemptNumber].(int); number != 0 {
|
||||
if number := storer.Users[email][StoreAttemptNumber].(int); number != 0 {
|
||||
t.Error("StoreLocked not set correctly:", number)
|
||||
}
|
||||
if locked := storer.Users["username"][StoreLocked].(bool); locked {
|
||||
if locked := storer.Users[email][StoreLocked].(bool); locked {
|
||||
t.Error("User should not be locked.")
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ func (r *Remember) AfterAuth(ctx *authboss.Context) error {
|
||||
return errUserMissing
|
||||
}
|
||||
|
||||
key, err := ctx.User.StringErr("username")
|
||||
key, err := ctx.User.StringErr(authboss.Cfg.PrimaryID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -140,7 +140,7 @@ func (r *Remember) Auth(
|
||||
}
|
||||
|
||||
// Ensure a half-auth.
|
||||
sstorer.Put(authboss.HalfAuthKey, "true")
|
||||
sstorer.Put(authboss.SessionHalfAuthKey, "true")
|
||||
// Log the user in.
|
||||
sstorer.Put(authboss.SessionKey, key)
|
||||
|
||||
|
@ -52,7 +52,7 @@ func TestAfterAuth(t *testing.T) {
|
||||
|
||||
ctx.SessionStorer = session
|
||||
ctx.CookieStorer = cookies
|
||||
ctx.User = authboss.Attributes{"username": "testuser"}
|
||||
ctx.User = authboss.Attributes{authboss.Cfg.PrimaryID: "test@email.com"}
|
||||
|
||||
if err := R.AfterAuth(ctx); err != nil {
|
||||
t.Error(err)
|
||||
@ -109,7 +109,7 @@ func TestAuth(t *testing.T) {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
if session.Values[authboss.HalfAuthKey] != "true" {
|
||||
if session.Values[authboss.SessionHalfAuthKey] != "true" {
|
||||
t.Error("The user should have been half-authed.")
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,6 @@ const (
|
||||
StoreEmail = "email"
|
||||
StoreUsername = "username"
|
||||
StorePassword = "password"
|
||||
// UserKey is used to uniquely identify the user.
|
||||
StoreKey = StoreEmail
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -22,9 +22,9 @@ func TestErrorList_Map(t *testing.T) {
|
||||
errAsploded := "asploded"
|
||||
|
||||
errList := ErrorList{
|
||||
FieldError{"username", errors.New(errNotLong)},
|
||||
FieldError{"username", errors.New(errEmail)},
|
||||
FieldError{"password", errors.New(errNotLong)},
|
||||
FieldError{StoreUsername, errors.New(errNotLong)},
|
||||
FieldError{StoreUsername, errors.New(errEmail)},
|
||||
FieldError{StorePassword, errors.New(errNotLong)},
|
||||
errors.New(errAsploded),
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ func TestErrorList_Map(t *testing.T) {
|
||||
t.Error("Wrong number of fields:", len(m))
|
||||
}
|
||||
|
||||
usernameErrs := m["username"]
|
||||
usernameErrs := m[StoreUsername]
|
||||
if len(usernameErrs) != 2 {
|
||||
t.Error("Wrong number of username errors:", len(usernameErrs))
|
||||
}
|
||||
@ -44,7 +44,7 @@ func TestErrorList_Map(t *testing.T) {
|
||||
t.Error("Wrong username error at 1:", usernameErrs[1])
|
||||
}
|
||||
|
||||
passwordErrs := m["password"]
|
||||
passwordErrs := m[StorePassword]
|
||||
if len(passwordErrs) != 1 {
|
||||
t.Error("Wrong number of password errors:", len(passwordErrs))
|
||||
}
|
||||
@ -64,30 +64,30 @@ func TestErrorList_Map(t *testing.T) {
|
||||
func TestValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := mockRequestContext("username", "john", "email", "john@john.com")
|
||||
ctx := mockRequestContext(StoreUsername, "john", StoreEmail, "john@john.com")
|
||||
|
||||
errList := ctx.Validate([]Validator{
|
||||
mockValidator{
|
||||
FieldName: "username",
|
||||
Errs: ErrorList{FieldError{"username", errors.New("must be longer than 4")}},
|
||||
FieldName: StoreUsername,
|
||||
Errs: ErrorList{FieldError{StoreUsername, errors.New("must be longer than 4")}},
|
||||
},
|
||||
mockValidator{
|
||||
FieldName: "missing_field",
|
||||
Errs: ErrorList{FieldError{"missing_field", errors.New("Expected field to exist.")}},
|
||||
},
|
||||
mockValidator{
|
||||
FieldName: "email", Errs: nil,
|
||||
FieldName: StoreEmail, Errs: nil,
|
||||
},
|
||||
})
|
||||
|
||||
errs := errList.Map()
|
||||
if errs["username"][0] != "must be longer than 4" {
|
||||
t.Error("Expected a different error for username:", errs["username"][0])
|
||||
if errs[StoreUsername][0] != "must be longer than 4" {
|
||||
t.Error("Expected a different error for username:", errs[StoreUsername][0])
|
||||
}
|
||||
if errs["missing_field"][0] != "Expected field to exist." {
|
||||
t.Error("Expected a different error for missing_field:", errs["missing_field"][0])
|
||||
}
|
||||
if _, ok := errs["email"]; ok {
|
||||
if _, ok := errs[StoreEmail]; ok {
|
||||
t.Error("Expected no errors for email.")
|
||||
}
|
||||
}
|
||||
@ -95,20 +95,20 @@ func TestValidate(t *testing.T) {
|
||||
func TestValidate_Confirm(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := mockRequestContext("username", "john", "confirmUsername", "johnny")
|
||||
errs := ctx.Validate(nil, "username", "confirmUsername").Map()
|
||||
ctx := mockRequestContext(StoreUsername, "john", "confirmUsername", "johnny")
|
||||
errs := ctx.Validate(nil, StoreUsername, "confirmUsername").Map()
|
||||
if errs["confirmUsername"][0] != "Does not match username" {
|
||||
t.Error("Expected a different error for confirmUsername:", errs["confirmUsername"][0])
|
||||
}
|
||||
|
||||
ctx = mockRequestContext("username", "john", "confirmUsername", "john")
|
||||
errs = ctx.Validate(nil, "username", "confirmUsername").Map()
|
||||
ctx = mockRequestContext(StoreUsername, "john", "confirmUsername", "john")
|
||||
errs = ctx.Validate(nil, StoreUsername, "confirmUsername").Map()
|
||||
if len(errs) != 0 {
|
||||
t.Error("Expected no errors:", errs)
|
||||
}
|
||||
|
||||
ctx = mockRequestContext("username", "john", "confirmUsername", "john")
|
||||
errs = ctx.Validate(nil, "username").Map()
|
||||
ctx = mockRequestContext(StoreUsername, "john", "confirmUsername", "john")
|
||||
errs = ctx.Validate(nil, StoreUsername).Map()
|
||||
if len(errs) != 0 {
|
||||
t.Error("Expected no errors:", errs)
|
||||
}
|
||||
@ -119,19 +119,19 @@ func TestFilterValidators(t *testing.T) {
|
||||
|
||||
validators := []Validator{
|
||||
mockValidator{
|
||||
FieldName: "username", Errs: ErrorList{FieldError{"username", errors.New("must be longer than 4")}},
|
||||
FieldName: StoreUsername, Errs: ErrorList{FieldError{StoreUsername, errors.New("must be longer than 4")}},
|
||||
},
|
||||
mockValidator{
|
||||
FieldName: "password", Errs: ErrorList{FieldError{"password", errors.New("must be longer than 4")}},
|
||||
FieldName: StorePassword, Errs: ErrorList{FieldError{StorePassword, errors.New("must be longer than 4")}},
|
||||
},
|
||||
}
|
||||
|
||||
validators = FilterValidators(validators, "username")
|
||||
validators = FilterValidators(validators, StoreUsername)
|
||||
|
||||
if len(validators) != 1 {
|
||||
t.Error("Expected length to be 1")
|
||||
}
|
||||
if validators[0].Field() != "username" {
|
||||
if validators[0].Field() != StoreUsername {
|
||||
t.Error("Expcted validator for field username", validators[0].Field())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user