2015-01-18 09:37:05 +02:00
|
|
|
package authboss
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
2015-08-02 20:51:35 +02:00
|
|
|
"net/http"
|
2015-01-18 09:37:05 +02:00
|
|
|
)
|
|
|
|
|
2015-02-23 12:03:29 +02:00
|
|
|
const (
|
|
|
|
// ConfirmPrefix is prepended to names of confirm fields.
|
|
|
|
ConfirmPrefix = "confirm_"
|
|
|
|
)
|
|
|
|
|
2015-01-25 02:07:41 +02:00
|
|
|
// Validator is anything that can validate a string and provide a list of errors
|
|
|
|
// and describe its set of rules.
|
|
|
|
type Validator interface {
|
|
|
|
Field() string
|
|
|
|
Errors(in string) ErrorList
|
|
|
|
Rules() []string
|
|
|
|
}
|
|
|
|
|
2015-03-16 23:42:45 +02:00
|
|
|
// ErrorList is simply a slice of errors with helpers.
|
2015-01-18 09:37:05 +02:00
|
|
|
type ErrorList []error
|
|
|
|
|
|
|
|
// Error satisfies the error interface.
|
|
|
|
func (e ErrorList) Error() string {
|
|
|
|
b := &bytes.Buffer{}
|
|
|
|
first := true
|
|
|
|
for _, err := range e {
|
|
|
|
if first {
|
|
|
|
first = false
|
|
|
|
} else {
|
|
|
|
b.WriteString(", ")
|
|
|
|
}
|
|
|
|
b.WriteString(err.Error())
|
|
|
|
}
|
|
|
|
return b.String()
|
|
|
|
}
|
|
|
|
|
2015-01-21 08:41:31 +02:00
|
|
|
// Map groups errors by their field name
|
|
|
|
func (e ErrorList) Map() map[string][]string {
|
|
|
|
m := make(map[string][]string)
|
|
|
|
|
|
|
|
for _, err := range e {
|
|
|
|
fieldErr, ok := err.(FieldError)
|
|
|
|
if !ok {
|
|
|
|
m[""] = append(m[""], err.Error())
|
|
|
|
} else {
|
|
|
|
m[fieldErr.Name] = append(m[fieldErr.Name], fieldErr.Err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
// FieldError represents an error that occurs during validation and is always
|
|
|
|
// attached to field on a form.
|
|
|
|
type FieldError struct {
|
|
|
|
Name string
|
|
|
|
Err error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f FieldError) Error() string {
|
|
|
|
return fmt.Sprintf("%s: %v", f.Name, f.Err)
|
|
|
|
}
|
|
|
|
|
2015-01-25 02:07:41 +02:00
|
|
|
// Validate validates a request using the given ruleset.
|
2015-08-02 22:00:16 +02:00
|
|
|
func Validate(r *http.Request, ruleset []Validator, confirmFields ...string) ErrorList {
|
2015-01-25 02:07:41 +02:00
|
|
|
errList := make(ErrorList, 0)
|
|
|
|
|
|
|
|
for _, validator := range ruleset {
|
|
|
|
field := validator.Field()
|
|
|
|
|
2015-08-02 20:51:35 +02:00
|
|
|
val := r.FormValue(field)
|
2015-01-25 02:07:41 +02:00
|
|
|
if errs := validator.Errors(val); len(errs) > 0 {
|
|
|
|
errList = append(errList, errs...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-26 08:58:50 +02:00
|
|
|
for i := 0; i < len(confirmFields)-1; i += 2 {
|
2015-08-02 20:51:35 +02:00
|
|
|
main := r.FormValue(confirmFields[i])
|
|
|
|
if len(main) == 0 {
|
2015-01-26 08:58:50 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2015-08-02 20:51:35 +02:00
|
|
|
confirm := r.FormValue(confirmFields[i+1])
|
|
|
|
if len(confirm) == 0 || main != confirm {
|
2015-01-26 08:58:50 +02:00
|
|
|
errList = append(errList, FieldError{confirmFields[i+1], fmt.Errorf("Does not match %s", confirmFields[i])})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-25 02:07:41 +02:00
|
|
|
return errList
|
2015-01-18 09:37:05 +02:00
|
|
|
}
|
2015-01-26 08:58:50 +02:00
|
|
|
|
2015-02-11 09:30:46 +02:00
|
|
|
// FilterValidators returns a subset of registered validators
|
2015-01-26 08:58:50 +02:00
|
|
|
func FilterValidators(validators []Validator, fields ...string) []Validator {
|
|
|
|
var arr []Validator
|
|
|
|
|
|
|
|
for _, validator := range validators {
|
|
|
|
fieldName := validator.Field()
|
|
|
|
for _, field := range fields {
|
|
|
|
if fieldName == field {
|
|
|
|
arr = append(arr, validator)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return arr
|
|
|
|
}
|