mirror of
https://github.com/astaxie/beego.git
synced 2024-11-25 23:21:45 +00:00
commit
a242f61b8e
177
validation/validation.go
Normal file
177
validation/validation.go
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package validation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidationError struct {
|
||||||
|
Message, Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the Message.
|
||||||
|
func (e *ValidationError) String() string {
|
||||||
|
if e == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return e.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Validation context manages data validation and error messages.
|
||||||
|
type Validation struct {
|
||||||
|
Errors []*ValidationError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Clear() {
|
||||||
|
v.Errors = []*ValidationError{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) HasErrors() bool {
|
||||||
|
return len(v.Errors) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the errors mapped by key.
|
||||||
|
// If there are multiple validation errors associated with a single key, the
|
||||||
|
// first one "wins". (Typically the first validation will be the more basic).
|
||||||
|
func (v *Validation) ErrorMap() map[string]*ValidationError {
|
||||||
|
m := map[string]*ValidationError{}
|
||||||
|
for _, e := range v.Errors {
|
||||||
|
if _, ok := m[e.Key]; !ok {
|
||||||
|
m[e.Key] = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an error to the validation context.
|
||||||
|
func (v *Validation) Error(message string, args ...interface{}) *ValidationResult {
|
||||||
|
result := (&ValidationResult{
|
||||||
|
Ok: false,
|
||||||
|
Error: &ValidationError{},
|
||||||
|
}).Message(message, args...)
|
||||||
|
v.Errors = append(v.Errors, result.Error)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ValidationResult is returned from every validation method.
|
||||||
|
// It provides an indication of success, and a pointer to the Error (if any).
|
||||||
|
type ValidationResult struct {
|
||||||
|
Error *ValidationError
|
||||||
|
Ok bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ValidationResult) Key(key string) *ValidationResult {
|
||||||
|
if r.Error != nil {
|
||||||
|
r.Error.Key = key
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ValidationResult) Message(message string, args ...interface{}) *ValidationResult {
|
||||||
|
if r.Error != nil {
|
||||||
|
if len(args) == 0 {
|
||||||
|
r.Error.Message = message
|
||||||
|
} else {
|
||||||
|
r.Error.Message = fmt.Sprintf(message, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the argument is non-nil and non-empty (if string or list)
|
||||||
|
func (v *Validation) Required(obj interface{}, key string) *ValidationResult {
|
||||||
|
return v.apply(Required{key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Min(n int, min int, key string) *ValidationResult {
|
||||||
|
return v.apply(Min{min, key}, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Max(n int, max int, key string) *ValidationResult {
|
||||||
|
return v.apply(Max{max, key}, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Range(n, min, max int, key string) *ValidationResult {
|
||||||
|
return v.apply(Range{Min{Min: min}, Max{Max: max}, key}, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) MinSize(obj interface{}, min int, key string) *ValidationResult {
|
||||||
|
return v.apply(MinSize{min, key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) MaxSize(obj interface{}, max int, key string) *ValidationResult {
|
||||||
|
return v.apply(MaxSize{max, key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Length(obj interface{}, n int, key string) *ValidationResult {
|
||||||
|
return v.apply(Length{n, key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Alpha(obj interface{}, key string) *ValidationResult {
|
||||||
|
return v.apply(Alpha{key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Numeric(obj interface{}, key string) *ValidationResult {
|
||||||
|
return v.apply(Numeric{key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) AlphaNumeric(obj interface{}, key string) *ValidationResult {
|
||||||
|
return v.apply(AlphaNumeric{key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Match(str string, regex *regexp.Regexp, key string) *ValidationResult {
|
||||||
|
return v.apply(Match{regex, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) NoMatch(str string, regex *regexp.Regexp, key string) *ValidationResult {
|
||||||
|
return v.apply(NoMatch{Match{Regexp: regex}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) AlphaDash(str string, key string) *ValidationResult {
|
||||||
|
return v.apply(AlphaDash{NoMatch{Match: Match{Regexp: alphaDashPattern}}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Email(str string, key string) *ValidationResult {
|
||||||
|
return v.apply(Email{Match{Regexp: emailPattern}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) IP(str string, key string) *ValidationResult {
|
||||||
|
return v.apply(IP{Match{Regexp: ipPattern}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Base64(str string, key string) *ValidationResult {
|
||||||
|
return v.apply(Base64{Match{Regexp: base64Pattern}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult {
|
||||||
|
if chk.IsSatisfied(obj) {
|
||||||
|
return &ValidationResult{Ok: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the error to the validation context.
|
||||||
|
err := &ValidationError{
|
||||||
|
Message: chk.DefaultMessage(),
|
||||||
|
Key: chk.GetKey(),
|
||||||
|
}
|
||||||
|
v.Errors = append(v.Errors, err)
|
||||||
|
|
||||||
|
// Also return it in the result.
|
||||||
|
return &ValidationResult{
|
||||||
|
Ok: false,
|
||||||
|
Error: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply a group of validators to a field, in order, and return the
|
||||||
|
// ValidationResult from the first one that fails, or the last one that
|
||||||
|
// succeeds.
|
||||||
|
func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResult {
|
||||||
|
var result *ValidationResult
|
||||||
|
for _, check := range checks {
|
||||||
|
result = v.apply(check, obj)
|
||||||
|
if !result.Ok {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
219
validation/validation_test.go
Normal file
219
validation/validation_test.go
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
package validation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRequired(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Required(nil, "nil").Ok {
|
||||||
|
t.Error("nil object should be false")
|
||||||
|
}
|
||||||
|
if valid.Required("", "string").Ok {
|
||||||
|
t.Error("\"'\" string should be false")
|
||||||
|
}
|
||||||
|
if !valid.Required("astaxie", "string").Ok {
|
||||||
|
t.Error("string should be true")
|
||||||
|
}
|
||||||
|
if valid.Required(0, "zero").Ok {
|
||||||
|
t.Error("Integer should not be equal 0")
|
||||||
|
}
|
||||||
|
if !valid.Required(1, "int").Ok {
|
||||||
|
t.Error("Integer except 0 should be true")
|
||||||
|
}
|
||||||
|
if !valid.Required(time.Now(), "time").Ok {
|
||||||
|
t.Error("time should be true")
|
||||||
|
}
|
||||||
|
if valid.Required([]string{}, "emptySlice").Ok {
|
||||||
|
t.Error("empty slice should be false")
|
||||||
|
}
|
||||||
|
if !valid.Required([]interface{}{"ok"}, "slice").Ok {
|
||||||
|
t.Error("slice should be equal true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMin(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Min(-1, 0, "min0").Ok {
|
||||||
|
t.Error("-1 is less than the minimum value of 0 should be false")
|
||||||
|
}
|
||||||
|
if !valid.Min(1, 0, "min0").Ok {
|
||||||
|
t.Error("1 is greater or equal than the minimum value of 0 should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMax(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Max(1, 0, "max0").Ok {
|
||||||
|
t.Error("1 is greater than the minimum value of 0 should be false")
|
||||||
|
}
|
||||||
|
if !valid.Max(-1, 0, "max0").Ok {
|
||||||
|
t.Error("-1 is less or equal than the maximum value of 0 should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRange(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Range(-1, 0, 1, "range0_1").Ok {
|
||||||
|
t.Error("-1 is bettween 0 and 1 should be false")
|
||||||
|
}
|
||||||
|
if !valid.Range(1, 0, 1, "range0_1").Ok {
|
||||||
|
t.Error("1 is bettween 0 and 1 should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMinSize(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.MinSize("", 1, "minSize1").Ok {
|
||||||
|
t.Error("the length of \"\" is less than the minimum value of 1 should be false")
|
||||||
|
}
|
||||||
|
if !valid.MinSize("ok", 1, "minSize1").Ok {
|
||||||
|
t.Error("the length of \"ok\" is greater or equal than the minimum value of 1 should be true")
|
||||||
|
}
|
||||||
|
if valid.MinSize([]string{}, 1, "minSize1").Ok {
|
||||||
|
t.Error("the length of empty slice is less than the minimum value of 1 should be false")
|
||||||
|
}
|
||||||
|
if !valid.MinSize([]interface{}{"ok"}, 1, "minSize1").Ok {
|
||||||
|
t.Error("the length of [\"ok\"] is greater or equal than the minimum value of 1 should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMaxSize(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.MaxSize("ok", 1, "maxSize1").Ok {
|
||||||
|
t.Error("the length of \"ok\" is greater than the maximum value of 1 should be false")
|
||||||
|
}
|
||||||
|
if !valid.MaxSize("", 1, "maxSize1").Ok {
|
||||||
|
t.Error("the length of \"\" is less or equal than the maximum value of 1 should be true")
|
||||||
|
}
|
||||||
|
if valid.MaxSize([]interface{}{"ok", false}, 1, "maxSize1").Ok {
|
||||||
|
t.Error("the length of [\"ok\", false] is greater than the maximum value of 1 should be false")
|
||||||
|
}
|
||||||
|
if !valid.MaxSize([]string{}, 1, "maxSize1").Ok {
|
||||||
|
t.Error("the length of empty slice is less or equal than the maximum value of 1 should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLength(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Length("", 1, "length1").Ok {
|
||||||
|
t.Error("the length of \"\" must equal 1 should be false")
|
||||||
|
}
|
||||||
|
if !valid.Length("1", 1, "length1").Ok {
|
||||||
|
t.Error("the length of \"1\" must equal 1 should be true")
|
||||||
|
}
|
||||||
|
if valid.Length([]string{}, 1, "length1").Ok {
|
||||||
|
t.Error("the length of empty slice must equal 1 should be false")
|
||||||
|
}
|
||||||
|
if !valid.Length([]interface{}{"ok"}, 1, "length1").Ok {
|
||||||
|
t.Error("the length of [\"ok\"] must equal 1 should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAlpha(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Alpha("a,1-@ $", "alpha").Ok {
|
||||||
|
t.Error("\"a,1-@ $\" are valid alpha characters should be false")
|
||||||
|
}
|
||||||
|
if !valid.Alpha("abCD", "alpha").Ok {
|
||||||
|
t.Error("\"abCD\" are valid alpha characters should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNumeric(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Numeric("a,1-@ $", "numeric").Ok {
|
||||||
|
t.Error("\"a,1-@ $\" are valid numeric characters should be false")
|
||||||
|
}
|
||||||
|
if !valid.Numeric("1234", "numeric").Ok {
|
||||||
|
t.Error("\"1234\" are valid numeric characters should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAlphaNumeric(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.AlphaNumeric("a,1-@ $", "alphaNumeric").Ok {
|
||||||
|
t.Error("\"a,1-@ $\" are valid alpha or numeric characters should be false")
|
||||||
|
}
|
||||||
|
if !valid.AlphaNumeric("1234aB", "alphaNumeric").Ok {
|
||||||
|
t.Error("\"1234aB\" are valid alpha or numeric characters should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatch(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Match("suchuangji@gmail", regexp.MustCompile("^\\w+@\\w+\\.\\w+$"), "match").Ok {
|
||||||
|
t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be false")
|
||||||
|
}
|
||||||
|
if !valid.Match("suchuangji@gmail.com", regexp.MustCompile("^\\w+@\\w+\\.\\w+$"), "match").Ok {
|
||||||
|
t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNoMatch(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.NoMatch("123@gmail", regexp.MustCompile("[^\\w\\d]"), "nomatch").Ok {
|
||||||
|
t.Error("\"123@gmail\" not match \"[^\\w\\d]\" should be false")
|
||||||
|
}
|
||||||
|
if !valid.NoMatch("123gmail", regexp.MustCompile("[^\\w\\d]"), "match").Ok {
|
||||||
|
t.Error("\"123@gmail\" not match \"[^\\w\\d@]\" should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAlphaDash(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.AlphaDash("a,1-@ $", "alphaDash").Ok {
|
||||||
|
t.Error("\"a,1-@ $\" are valid alpha or numeric or dash(-_) characters should be false")
|
||||||
|
}
|
||||||
|
if !valid.AlphaDash("1234aB-_", "alphaDash").Ok {
|
||||||
|
t.Error("\"1234aB\" are valid alpha or numeric or dash(-_) characters should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmail(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Email("not@a email", "email").Ok {
|
||||||
|
t.Error("\"not@a email\" is a valid email address should be false")
|
||||||
|
}
|
||||||
|
if !valid.Email("suchuangji@gmail.com", "email").Ok {
|
||||||
|
t.Error("\"suchuangji@gmail.com\" is a valid email address should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIP(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.IP("11.255.255.256", "IP").Ok {
|
||||||
|
t.Error("\"11.255.255.256\" is a valid ip address should be false")
|
||||||
|
}
|
||||||
|
if !valid.IP("01.11.11.11", "IP").Ok {
|
||||||
|
t.Error("\"suchuangji@gmail.com\" is a valid ip address should be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBase64(t *testing.T) {
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
if valid.Base64("suchuangji@gmail.com", "base64").Ok {
|
||||||
|
t.Error("\"suchuangji@gmail.com\" are a valid base64 characters should be false")
|
||||||
|
}
|
||||||
|
if !valid.Base64("c3VjaHVhbmdqaUBnbWFpbC5jb20=", "base64").Ok {
|
||||||
|
t.Error("\"c3VjaHVhbmdqaUBnbWFpbC5jb20=\" are a valid base64 characters should be true")
|
||||||
|
}
|
||||||
|
}
|
355
validation/validators.go
Normal file
355
validation/validators.go
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
package validation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Validator interface {
|
||||||
|
IsSatisfied(interface{}) bool
|
||||||
|
DefaultMessage() string
|
||||||
|
GetKey() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Required struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Required) IsSatisfied(obj interface{}) bool {
|
||||||
|
if obj == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if str, ok := obj.(string); ok {
|
||||||
|
return len(str) > 0
|
||||||
|
}
|
||||||
|
if b, ok := obj.(bool); ok {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
if i, ok := obj.(int); ok {
|
||||||
|
return i != 0
|
||||||
|
}
|
||||||
|
if t, ok := obj.(time.Time); ok {
|
||||||
|
return !t.IsZero()
|
||||||
|
}
|
||||||
|
v := reflect.ValueOf(obj)
|
||||||
|
if v.Kind() == reflect.Slice {
|
||||||
|
return v.Len() > 0
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Required) DefaultMessage() string {
|
||||||
|
return "Required"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Required) GetKey() string {
|
||||||
|
return r.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type Min struct {
|
||||||
|
Min int
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Min) IsSatisfied(obj interface{}) bool {
|
||||||
|
num, ok := obj.(int)
|
||||||
|
if ok {
|
||||||
|
return num >= m.Min
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Min) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Minimum is", m.Min)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Min) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type Max struct {
|
||||||
|
Max int
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Max) IsSatisfied(obj interface{}) bool {
|
||||||
|
num, ok := obj.(int)
|
||||||
|
if ok {
|
||||||
|
return num <= m.Max
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Max) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Maximum is", m.Max)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Max) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires an integer to be within Min, Max inclusive.
|
||||||
|
type Range struct {
|
||||||
|
Min
|
||||||
|
Max
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Range) IsSatisfied(obj interface{}) bool {
|
||||||
|
return r.Min.IsSatisfied(obj) && r.Max.IsSatisfied(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Range) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Range is", r.Min.Min, "to", r.Max.Max)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Range) GetKey() string {
|
||||||
|
return r.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires an array or string to be at least a given length.
|
||||||
|
type MinSize struct {
|
||||||
|
Min int
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MinSize) IsSatisfied(obj interface{}) bool {
|
||||||
|
if str, ok := obj.(string); ok {
|
||||||
|
return len(str) >= m.Min
|
||||||
|
}
|
||||||
|
v := reflect.ValueOf(obj)
|
||||||
|
if v.Kind() == reflect.Slice {
|
||||||
|
return v.Len() >= m.Min
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MinSize) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Minimum size is", m.Min)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MinSize) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires an array or string to be at most a given length.
|
||||||
|
type MaxSize struct {
|
||||||
|
Max int
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MaxSize) IsSatisfied(obj interface{}) bool {
|
||||||
|
if str, ok := obj.(string); ok {
|
||||||
|
return len(str) <= m.Max
|
||||||
|
}
|
||||||
|
v := reflect.ValueOf(obj)
|
||||||
|
if v.Kind() == reflect.Slice {
|
||||||
|
return v.Len() <= m.Max
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MaxSize) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Maximum size is", m.Max)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MaxSize) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires an array or string to be exactly a given length.
|
||||||
|
type Length struct {
|
||||||
|
N int
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Length) IsSatisfied(obj interface{}) bool {
|
||||||
|
if str, ok := obj.(string); ok {
|
||||||
|
return len(str) == l.N
|
||||||
|
}
|
||||||
|
v := reflect.ValueOf(obj)
|
||||||
|
if v.Kind() == reflect.Slice {
|
||||||
|
return v.Len() == l.N
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Length) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Required length is", l.N)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Length) GetKey() string {
|
||||||
|
return l.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type Alpha struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Alpha) IsSatisfied(obj interface{}) bool {
|
||||||
|
if str, ok := obj.(string); ok {
|
||||||
|
for _, v := range str {
|
||||||
|
if ('Z' < v || v < 'A') && ('z' < v || v < 'a') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Alpha) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must be valid alpha characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Alpha) GetKey() string {
|
||||||
|
return a.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type Numeric struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n Numeric) IsSatisfied(obj interface{}) bool {
|
||||||
|
if str, ok := obj.(string); ok {
|
||||||
|
for _, v := range str {
|
||||||
|
if '9' < v || v < '0' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n Numeric) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must be valid numeric characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n Numeric) GetKey() string {
|
||||||
|
return n.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type AlphaNumeric struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AlphaNumeric) IsSatisfied(obj interface{}) bool {
|
||||||
|
if str, ok := obj.(string); ok {
|
||||||
|
for _, v := range str {
|
||||||
|
if ('Z' < v || v < 'A') && ('z' < v || v < 'a') && ('9' < v || v < '0') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AlphaNumeric) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must be valid alpha or numeric characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AlphaNumeric) GetKey() string {
|
||||||
|
return a.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires a string to match a given regex.
|
||||||
|
type Match struct {
|
||||||
|
Regexp *regexp.Regexp
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Match) IsSatisfied(obj interface{}) bool {
|
||||||
|
str := obj.(string)
|
||||||
|
return m.Regexp.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Match) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must match", m.Regexp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Match) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires a string to not match a given regex.
|
||||||
|
type NoMatch struct {
|
||||||
|
Match
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NoMatch) IsSatisfied(obj interface{}) bool {
|
||||||
|
return !n.Match.IsSatisfied(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NoMatch) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must not match", n.Regexp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NoMatch) GetKey() string {
|
||||||
|
return n.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
var alphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
|
||||||
|
|
||||||
|
type AlphaDash struct {
|
||||||
|
NoMatch
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AlphaDash) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must be valid alpha or numeric or dash(-_) characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AlphaDash) GetKey() string {
|
||||||
|
return a.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
var emailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
|
||||||
|
|
||||||
|
type Email struct {
|
||||||
|
Match
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Email) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must be a valid email address")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Email) GetKey() string {
|
||||||
|
return e.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipPattern = regexp.MustCompile("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$")
|
||||||
|
|
||||||
|
type IP struct {
|
||||||
|
Match
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i IP) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must be a valid ip address")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i IP) GetKey() string {
|
||||||
|
return i.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
var base64Pattern = regexp.MustCompile("^(?:[A-Za-z0-99+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")
|
||||||
|
|
||||||
|
type Base64 struct {
|
||||||
|
Match
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Base64) DefaultMessage() string {
|
||||||
|
return fmt.Sprintln("Must be valid base64 characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Base64) GetKey() string {
|
||||||
|
return b.Key
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user