1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-10-30 23:47:59 +02:00

Add PrimaryID to the system.

- Fix #17
This commit is contained in:
Aaron
2015-02-22 13:16:11 -08:00
parent 4eeb21e16d
commit 001810bf7c
12 changed files with 96 additions and 84 deletions

View File

@@ -14,9 +14,6 @@ const (
methodPOST = "POST" methodPOST = "POST"
tplLogin = "login.tpl" tplLogin = "login.tpl"
storeUsername = "username"
storePassword = "password"
) )
func init() { func init() {
@@ -37,7 +34,7 @@ func (a *AuthModule) Initialize() (err error) {
return err 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.isRememberLoaded = authboss.IsLoaded("remember")
a.isRecoverLoaded = authboss.IsLoaded("recover") a.isRecoverLoaded = authboss.IsLoaded("recover")
@@ -54,8 +51,8 @@ func (a *AuthModule) Routes() authboss.RouteTable {
func (a *AuthModule) Storage() authboss.StorageOptions { func (a *AuthModule) Storage() authboss.StorageOptions {
return authboss.StorageOptions{ return authboss.StorageOptions{
storeUsername: authboss.String, authboss.Cfg.PrimaryID: authboss.String,
storePassword: authboss.String, authboss.StorePassword: authboss.String,
} }
} }
@@ -63,7 +60,7 @@ func (a *AuthModule) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWrit
switch r.Method { switch r.Method {
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.SessionHalfAuthKey); !ok || halfAuthed == "false" {
http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound) 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 return nil
} }
username, _ := ctx.FirstPostFormValue("username") key, _ := ctx.FirstPostFormValue(authboss.Cfg.PrimaryID)
password, _ := ctx.FirstPostFormValue("password") password, _ := ctx.FirstPostFormValue("password")
errData := authboss.NewHTMLData( errData := authboss.NewHTMLData(
"error", "invalid username and/or password", "error", "invalid username and/or password",
"username", username, authboss.Cfg.PrimaryID, key,
"showRemember", a.isRememberLoaded, "showRemember", a.isRememberLoaded,
"showRecover", a.isRecoverLoaded, "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) 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) fmt.Fprintln(authboss.Cfg.LogWriter, "auth: failed to validate credentials:", err)
return a.templates.Render(ctx, w, r, tplLogin, errData) 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) authboss.Cfg.Callbacks.FireAfter(authboss.EventAuth, ctx)
http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound) http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound)
default: default:
@@ -116,12 +113,12 @@ func (a *AuthModule) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWrit
return nil return nil
} }
func validateCredentials(ctx *authboss.Context, username, password string) error { func validateCredentials(ctx *authboss.Context, key, password string) error {
if err := ctx.LoadUser(username); err != nil { if err := ctx.LoadUser(key); err != nil {
return err return err
} }
actualPassword, err := ctx.User.StringErr(storePassword) actualPassword, err := ctx.User.StringErr(authboss.StorePassword)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -8,7 +8,7 @@ const (
// HalfAuthKey is used for sessions that have been authenticated by // HalfAuthKey is used for sessions that have been authenticated by
// the remember module. This serves as a way to force full authentication // the remember module. This serves as a way to force full authentication
// by denying half-authed users acccess to sensitive areas. // 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 is used for storing sucess flash messages on the session
FlashSuccessKey = "flash_success" FlashSuccessKey = "flash_success"
// FlashErrorKey is used for storing sucess flash messages on the session // FlashErrorKey is used for storing sucess flash messages on the session

View File

@@ -5,6 +5,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/smtp" "net/smtp"
"strings"
"time" "time"
"golang.org/x/crypto/bcrypt" "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. // 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 authboss's routes at (eg /auth).
MountPath string MountPath string
// ViewsPath is the path to overiding view template files. // ViewsPath is the path to search for overridden templates.
ViewsPath string 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 HostName string
// BCryptPasswordCost is self explanitory. // BCryptCost is the cost of the bcrypt password hashing function.
BCryptCost int 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 Layout *template.Template
LayoutEmail *template.Template LayoutEmail *template.Template
LayoutDataMaker ViewDataMaker LayoutDataMaker ViewDataMaker
@@ -45,7 +50,8 @@ type Config struct {
Policies []Validator Policies []Validator
ConfirmFields []string ConfirmFields []string
ExpireAfter time.Duration ExpireAfter time.Duration
LockAfter int LockAfter int
LockWindow time.Duration LockWindow time.Duration
LockDuration time.Duration LockDuration time.Duration
@@ -73,6 +79,8 @@ func NewConfig() *Config {
HostName: "localhost:8080", HostName: "localhost:8080",
BCryptCost: bcrypt.DefaultCost, BCryptCost: bcrypt.DefaultCost,
PrimaryID: StoreEmail,
Layout: template.Must(template.New("").Parse(`<html><body>{{template "authboss" .}}</body></html>`)), Layout: template.Must(template.New("").Parse(`<html><body>{{template "authboss" .}}</body></html>`)),
LayoutEmail: 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, AllowWhitespace: false,
}, },
}, },
ConfirmFields: []string{"username", "confirmUsername", "password", "confirmPassword"}, ConfirmFields: []string{
StoreEmail, "confirm" + strings.Title(StoreEmail),
StorePassword, "confirm" + strings.Title(StorePassword),
},
RecoverRedirect: "/login", RecoverRedirect: "/login",
RecoverInitiateSuccessFlash: "An email has been sent with further insructions on how to reset your password", RecoverInitiateSuccessFlash: "An email has been sent with further insructions on how to reset your password",

View File

@@ -98,6 +98,7 @@ func TestConfirm_AfterRegister(t *testing.T) {
log := &bytes.Buffer{} log := &bytes.Buffer{}
authboss.Cfg.LogWriter = log authboss.Cfg.LogWriter = log
authboss.Cfg.Mailer = authboss.LogMailer(log) authboss.Cfg.Mailer = authboss.LogMailer(log)
authboss.Cfg.PrimaryID = authboss.StoreUsername
sentEmail := false sentEmail := false
@@ -110,7 +111,7 @@ func TestConfirm_AfterRegister(t *testing.T) {
t.Error("Expected it to die with user error:", err) 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" { if err := c.AfterRegister(ctx); err == nil || err.(authboss.AttributeErr).Name != "email" {
t.Error("Expected it to die with e-mail address error:", err) t.Error("Expected it to die with e-mail address error:", err)
} }

View File

@@ -130,7 +130,7 @@ func (c *Context) SaveUser() error {
return errors.New("User not initialized.") return errors.New("User not initialized.")
} }
key, ok := c.User.String("username") key, ok := c.User.String(Cfg.PrimaryID)
if !ok { if !ok {
return errors.New("User improperly initialized, primary ID missing") return errors.New("User improperly initialized, primary ID missing")
} }

View File

@@ -41,14 +41,14 @@ func TestContext_SaveUser(t *testing.T) {
ctx := NewContext() ctx := NewContext()
storer := mockStorer{} storer := mockStorer{}
Cfg.Storer = storer 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() err := ctx.SaveUser()
if err != nil { if err != nil {
t.Error("Unexpected error:", err) t.Error("Unexpected error:", err)
} }
attr, ok := storer["joe"] attr, ok := storer["hello@joe.com"]
if !ok { if !ok {
t.Error("Could not find joe!") t.Error("Could not find joe!")
} }

View File

@@ -74,7 +74,7 @@ func TestExpire_Middleware(t *testing.T) {
authboss.NewConfig() authboss.NewConfig()
session := mocks.NewMockClientStorer() session := mocks.NewMockClientStorer()
session.Values = map[string]string{ 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 } maker := func(w http.ResponseWriter, r *http.Request) authboss.ClientStorer { return session }

View File

@@ -49,15 +49,15 @@ func TestAfterAuth(t *testing.T) {
storer := mocks.NewMockStorer() storer := mocks.NewMockStorer()
authboss.Cfg.Storer = storer 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 { if err := lock.AfterAuth(ctx); err != nil {
t.Error(err) t.Error(err)
} }
if storer.Users["username"][StoreAttemptNumber].(int) != 0 { if storer.Users["john@john.com"][StoreAttemptNumber].(int) != 0 {
t.Error("StoreAttemptNumber set incorrectly.") 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.") t.Error("StoreAttemptTime not set.")
} }
} }
@@ -74,35 +74,37 @@ func TestAfterAuthFail_Lock(t *testing.T) {
authboss.Cfg.LockWindow = 30 * time.Minute authboss.Cfg.LockWindow = 30 * time.Minute
authboss.Cfg.LockAfter = 3 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) old = time.Now().UTC().Add(-1 * time.Hour)
for i := 0; i < 3; i++ { 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) t.Errorf("%d: User should not be locked.", i)
} }
if err := lock.AfterAuthFail(ctx); err != nil { if err := lock.AfterAuthFail(ctx); err != nil {
t.Error(err) 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) 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) t.Error("%d: StoreAttemptTime not set correctly: %v", i, current)
} }
current = old current = old
} }
if !storer.Users["username"][StoreLocked].(bool) { if !storer.Users[email][StoreLocked].(bool) {
t.Error("User should be locked.") 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) 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.") t.Error("StoreAttemptTime not set correctly.")
} }
} }
@@ -120,21 +122,22 @@ func TestAfterAuthFail_Reset(t *testing.T) {
old = time.Now().UTC().Add(-time.Hour) old = time.Now().UTC().Add(-time.Hour)
email := "john@john.com"
ctx.User = map[string]interface{}{ ctx.User = map[string]interface{}{
"username": "username", authboss.Cfg.PrimaryID: email,
StoreAttemptNumber: 2, StoreAttemptNumber: 2,
StoreAttemptTime: old, StoreAttemptTime: old,
StoreLocked: false, StoreLocked: false,
} }
lock.AfterAuthFail(ctx) 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) 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.") 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) t.Error("StoreLocked not set correctly:", locked)
} }
} }
@@ -156,17 +159,18 @@ func TestLock(t *testing.T) {
authboss.Cfg.Storer = storer authboss.Cfg.Storer = storer
lock := Lock{} lock := Lock{}
storer.Users["username"] = map[string]interface{}{ email := "john@john.com"
"username": "username", storer.Users[email] = map[string]interface{}{
"password": "password", authboss.Cfg.PrimaryID: email,
"password": "password",
} }
err := lock.Lock("username") err := lock.Lock(email)
if err != nil { if err != nil {
t.Error(err) 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.") t.Error("User should be locked.")
} }
} }
@@ -178,25 +182,26 @@ func TestUnlock(t *testing.T) {
lock := Lock{} lock := Lock{}
authboss.Cfg.LockWindow = 1 * time.Hour authboss.Cfg.LockWindow = 1 * time.Hour
storer.Users["username"] = map[string]interface{}{ email := "john@john.com"
"username": "username", storer.Users[email] = map[string]interface{}{
"password": "password", authboss.Cfg.PrimaryID: email,
"locked": true, "password": "password",
"locked": true,
} }
err := lock.Unlock("username") err := lock.Unlock(email)
if err != nil { if err != nil {
t.Error(err) 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)) { if attemptTime.After(time.Now().UTC().Add(-authboss.Cfg.LockWindow)) {
t.Error("StoreLocked not set correctly:", attemptTime) 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) 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.") t.Error("User should not be locked.")
} }
} }

View File

@@ -68,7 +68,7 @@ func (r *Remember) AfterAuth(ctx *authboss.Context) error {
return errUserMissing return errUserMissing
} }
key, err := ctx.User.StringErr("username") key, err := ctx.User.StringErr(authboss.Cfg.PrimaryID)
if err != nil { if err != nil {
return err return err
} }
@@ -140,7 +140,7 @@ func (r *Remember) Auth(
} }
// Ensure a half-auth. // Ensure a half-auth.
sstorer.Put(authboss.HalfAuthKey, "true") sstorer.Put(authboss.SessionHalfAuthKey, "true")
// Log the user in. // Log the user in.
sstorer.Put(authboss.SessionKey, key) sstorer.Put(authboss.SessionKey, key)

View File

@@ -52,7 +52,7 @@ func TestAfterAuth(t *testing.T) {
ctx.SessionStorer = session ctx.SessionStorer = session
ctx.CookieStorer = cookies 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 { if err := R.AfterAuth(ctx); err != nil {
t.Error(err) t.Error(err)
@@ -109,7 +109,7 @@ func TestAuth(t *testing.T) {
t.Error("Unexpected error:", err) 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.") t.Error("The user should have been half-authed.")
} }

View File

@@ -14,8 +14,6 @@ const (
StoreEmail = "email" StoreEmail = "email"
StoreUsername = "username" StoreUsername = "username"
StorePassword = "password" StorePassword = "password"
// UserKey is used to uniquely identify the user.
StoreKey = StoreEmail
) )
var ( var (

View File

@@ -22,9 +22,9 @@ func TestErrorList_Map(t *testing.T) {
errAsploded := "asploded" errAsploded := "asploded"
errList := ErrorList{ errList := ErrorList{
FieldError{"username", errors.New(errNotLong)}, FieldError{StoreUsername, errors.New(errNotLong)},
FieldError{"username", errors.New(errEmail)}, FieldError{StoreUsername, errors.New(errEmail)},
FieldError{"password", errors.New(errNotLong)}, FieldError{StorePassword, errors.New(errNotLong)},
errors.New(errAsploded), errors.New(errAsploded),
} }
@@ -33,7 +33,7 @@ func TestErrorList_Map(t *testing.T) {
t.Error("Wrong number of fields:", len(m)) t.Error("Wrong number of fields:", len(m))
} }
usernameErrs := m["username"] usernameErrs := m[StoreUsername]
if len(usernameErrs) != 2 { if len(usernameErrs) != 2 {
t.Error("Wrong number of username errors:", len(usernameErrs)) 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]) t.Error("Wrong username error at 1:", usernameErrs[1])
} }
passwordErrs := m["password"] passwordErrs := m[StorePassword]
if len(passwordErrs) != 1 { if len(passwordErrs) != 1 {
t.Error("Wrong number of password errors:", len(passwordErrs)) t.Error("Wrong number of password errors:", len(passwordErrs))
} }
@@ -64,30 +64,30 @@ func TestErrorList_Map(t *testing.T) {
func TestValidate(t *testing.T) { func TestValidate(t *testing.T) {
t.Parallel() t.Parallel()
ctx := mockRequestContext("username", "john", "email", "john@john.com") ctx := mockRequestContext(StoreUsername, "john", StoreEmail, "john@john.com")
errList := ctx.Validate([]Validator{ errList := ctx.Validate([]Validator{
mockValidator{ mockValidator{
FieldName: "username", FieldName: StoreUsername,
Errs: ErrorList{FieldError{"username", errors.New("must be longer than 4")}}, Errs: ErrorList{FieldError{StoreUsername, errors.New("must be longer than 4")}},
}, },
mockValidator{ mockValidator{
FieldName: "missing_field", FieldName: "missing_field",
Errs: ErrorList{FieldError{"missing_field", errors.New("Expected field to exist.")}}, Errs: ErrorList{FieldError{"missing_field", errors.New("Expected field to exist.")}},
}, },
mockValidator{ mockValidator{
FieldName: "email", Errs: nil, FieldName: StoreEmail, Errs: nil,
}, },
}) })
errs := errList.Map() errs := errList.Map()
if errs["username"][0] != "must be longer than 4" { if errs[StoreUsername][0] != "must be longer than 4" {
t.Error("Expected a different error for username:", errs["username"][0]) t.Error("Expected a different error for username:", errs[StoreUsername][0])
} }
if errs["missing_field"][0] != "Expected field to exist." { if errs["missing_field"][0] != "Expected field to exist." {
t.Error("Expected a different error for missing_field:", errs["missing_field"][0]) 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.") t.Error("Expected no errors for email.")
} }
} }
@@ -95,20 +95,20 @@ func TestValidate(t *testing.T) {
func TestValidate_Confirm(t *testing.T) { func TestValidate_Confirm(t *testing.T) {
t.Parallel() t.Parallel()
ctx := mockRequestContext("username", "john", "confirmUsername", "johnny") ctx := mockRequestContext(StoreUsername, "john", "confirmUsername", "johnny")
errs := ctx.Validate(nil, "username", "confirmUsername").Map() errs := ctx.Validate(nil, StoreUsername, "confirmUsername").Map()
if errs["confirmUsername"][0] != "Does not match username" { if errs["confirmUsername"][0] != "Does not match username" {
t.Error("Expected a different error for confirmUsername:", errs["confirmUsername"][0]) t.Error("Expected a different error for confirmUsername:", errs["confirmUsername"][0])
} }
ctx = mockRequestContext("username", "john", "confirmUsername", "john") ctx = mockRequestContext(StoreUsername, "john", "confirmUsername", "john")
errs = ctx.Validate(nil, "username", "confirmUsername").Map() errs = ctx.Validate(nil, StoreUsername, "confirmUsername").Map()
if len(errs) != 0 { if len(errs) != 0 {
t.Error("Expected no errors:", errs) t.Error("Expected no errors:", errs)
} }
ctx = mockRequestContext("username", "john", "confirmUsername", "john") ctx = mockRequestContext(StoreUsername, "john", "confirmUsername", "john")
errs = ctx.Validate(nil, "username").Map() errs = ctx.Validate(nil, StoreUsername).Map()
if len(errs) != 0 { if len(errs) != 0 {
t.Error("Expected no errors:", errs) t.Error("Expected no errors:", errs)
} }
@@ -119,19 +119,19 @@ func TestFilterValidators(t *testing.T) {
validators := []Validator{ validators := []Validator{
mockValidator{ 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{ 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 { if len(validators) != 1 {
t.Error("Expected length to be 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()) t.Error("Expcted validator for field username", validators[0].Field())
} }
} }