update gt, gte, lt and let to handle dates compared to time.Now().UTC()
pull/16/head
Dean Karn 10 years ago
parent 5a0fdabb75
commit e882184fe2
  1. 100
      baked_in.go
  2. 15
      validator.go
  3. 119
      validator_test.go

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
"reflect" "reflect"
"strconv" "strconv"
"time"
) )
// BakedInValidators is the map of ValidationFunc used internally // BakedInValidators is the map of ValidationFunc used internally
@ -43,9 +44,9 @@ func isURI(field interface{}, param string) bool {
_, err := url.ParseRequestURI(field.(string)) _, err := url.ParseRequestURI(field.(string))
return err == nil return err == nil
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isURL(field interface{}, param string) bool { func isURL(field interface{}, param string) bool {
@ -66,11 +67,10 @@ func isURL(field interface{}, param string) bool {
} }
return err == nil return err == nil
}
default:
panic(fmt.Sprintf("Bad field type %T", field)) panic(fmt.Sprintf("Bad field type %T", field))
} }
}
func isEmail(field interface{}, param string) bool { func isEmail(field interface{}, param string) bool {
@ -80,9 +80,9 @@ func isEmail(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return emailRegex.MatchString(field.(string)) return emailRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isHsla(field interface{}, param string) bool { func isHsla(field interface{}, param string) bool {
@ -93,9 +93,9 @@ func isHsla(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return hslaRegex.MatchString(field.(string)) return hslaRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isHsl(field interface{}, param string) bool { func isHsl(field interface{}, param string) bool {
@ -106,9 +106,9 @@ func isHsl(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return hslRegex.MatchString(field.(string)) return hslRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isRgba(field interface{}, param string) bool { func isRgba(field interface{}, param string) bool {
@ -119,9 +119,9 @@ func isRgba(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return rgbaRegex.MatchString(field.(string)) return rgbaRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isRgb(field interface{}, param string) bool { func isRgb(field interface{}, param string) bool {
@ -132,9 +132,9 @@ func isRgb(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return rgbRegex.MatchString(field.(string)) return rgbRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isHexcolor(field interface{}, param string) bool { func isHexcolor(field interface{}, param string) bool {
@ -145,9 +145,9 @@ func isHexcolor(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return hexcolorRegex.MatchString(field.(string)) return hexcolorRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isHexadecimal(field interface{}, param string) bool { func isHexadecimal(field interface{}, param string) bool {
@ -158,9 +158,9 @@ func isHexadecimal(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return hexadecimalRegex.MatchString(field.(string)) return hexadecimalRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isNumber(field interface{}, param string) bool { func isNumber(field interface{}, param string) bool {
@ -171,9 +171,9 @@ func isNumber(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return numberRegex.MatchString(field.(string)) return numberRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isNumeric(field interface{}, param string) bool { func isNumeric(field interface{}, param string) bool {
@ -184,9 +184,9 @@ func isNumeric(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return numericRegex.MatchString(field.(string)) return numericRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isAlphanum(field interface{}, param string) bool { func isAlphanum(field interface{}, param string) bool {
@ -197,9 +197,9 @@ func isAlphanum(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return alphaNumericRegex.MatchString(field.(string)) return alphaNumericRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isAlpha(field interface{}, param string) bool { func isAlpha(field interface{}, param string) bool {
@ -210,9 +210,9 @@ func isAlpha(field interface{}, param string) bool {
case reflect.String: case reflect.String:
return alphaRegex.MatchString(field.(string)) return alphaRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func hasValue(field interface{}, param string) bool { func hasValue(field interface{}, param string) bool {
@ -260,11 +260,20 @@ func isGte(field interface{}, param string) bool {
return st.Float() >= p return st.Float() >= p
default: case reflect.Struct:
panic(fmt.Sprintf("Bad field type %T", field))
if st.Type() == reflect.TypeOf(field) {
now := time.Now().UTC()
t := field.(time.Time)
return t.After(now) || t.Equal(now)
} }
} }
panic(fmt.Sprintf("Bad field type %T", field))
}
func isGt(field interface{}, param string) bool { func isGt(field interface{}, param string) bool {
st := reflect.ValueOf(field) st := reflect.ValueOf(field)
@ -295,12 +304,17 @@ func isGt(field interface{}, param string) bool {
p := asFloat(param) p := asFloat(param)
return st.Float() > p return st.Float() > p
case reflect.Struct:
default: if st.Type() == reflect.TypeOf(field) {
panic(fmt.Sprintf("Bad field type %T", field))
return field.(time.Time).After(time.Now().UTC())
} }
} }
panic(fmt.Sprintf("Bad field type %T", field))
}
// length tests whether a variable's length is equal to a given // length tests whether a variable's length is equal to a given
// value. For strings it tests the number of characters whereas // value. For strings it tests the number of characters whereas
// for maps and slices it tests the number of items. // for maps and slices it tests the number of items.
@ -334,11 +348,10 @@ func hasLengthOf(field interface{}, param string) bool {
p := asFloat(param) p := asFloat(param)
return st.Float() == p return st.Float() == p
}
default:
panic(fmt.Sprintf("Bad field type %T", field)) panic(fmt.Sprintf("Bad field type %T", field))
} }
}
// min tests whether a variable value is larger or equal to a given // min tests whether a variable value is larger or equal to a given
// number. For number types, it's a simple lesser-than test; for // number. For number types, it's a simple lesser-than test; for
@ -380,11 +393,20 @@ func isLte(field interface{}, param string) bool {
return st.Float() <= p return st.Float() <= p
default: case reflect.Struct:
panic(fmt.Sprintf("Bad field type %T", field))
if st.Type() == reflect.TypeOf(field) {
now := time.Now().UTC()
t := field.(time.Time)
return t.Before(now) || t.Equal(now)
} }
} }
panic(fmt.Sprintf("Bad field type %T", field))
}
func isLt(field interface{}, param string) bool { func isLt(field interface{}, param string) bool {
st := reflect.ValueOf(field) st := reflect.ValueOf(field)
@ -416,9 +438,15 @@ func isLt(field interface{}, param string) bool {
return st.Float() < p return st.Float() < p
default: case reflect.Struct:
panic(fmt.Sprintf("Bad field type %T", field))
if st.Type() == reflect.TypeOf(field) {
return field.(time.Time).Before(time.Now().UTC())
}
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
// max tests whether a variable value is lesser than a given // max tests whether a variable value is lesser than a given

@ -13,6 +13,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
"time"
"unicode" "unicode"
) )
@ -215,11 +216,22 @@ func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {
continue continue
} }
if valueField.Type() == reflect.TypeOf(time.Time{}) {
if fieldError := v.validateFieldByNameAndTag(valueField.Interface(), typeField.Name, tag); fieldError != nil {
validationErrors.Errors[fieldError.Field] = fieldError
// free up memory reference
fieldError = nil
}
} else {
if structErrors := v.ValidateStruct(valueField.Interface()); structErrors != nil { if structErrors := v.ValidateStruct(valueField.Interface()); structErrors != nil {
validationErrors.StructErrors[typeField.Name] = structErrors validationErrors.StructErrors[typeField.Name] = structErrors
// free up memory map no longer needed // free up memory map no longer needed
structErrors = nil structErrors = nil
} }
}
default: default:
@ -270,8 +282,11 @@ func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag st
switch valueField.Kind() { switch valueField.Kind() {
case reflect.Struct, reflect.Interface, reflect.Invalid: case reflect.Struct, reflect.Interface, reflect.Invalid:
if valueField.Type() != reflect.TypeOf(time.Time{}) {
panic("Invalid field passed to ValidateFieldWithTag") panic("Invalid field passed to ValidateFieldWithTag")
} }
}
var valErr *FieldValidationError var valErr *FieldValidationError
var err error var err error

@ -3,6 +3,7 @@ package validator_test
import ( import (
"fmt" "fmt"
"testing" "testing"
"time"
"github.com/joeybloggs/go-validate-yourself" "github.com/joeybloggs/go-validate-yourself"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
@ -218,12 +219,70 @@ func (ms *MySuite) TestIsGt(c *C) {
i := true i := true
c.Assert(func() { validator.ValidateFieldByTag(i, "gt") }, PanicMatches, "Bad field type bool") c.Assert(func() { validator.ValidateFieldByTag(i, "gt") }, PanicMatches, "Bad field type bool")
t := time.Now().UTC()
t = t.Add(time.Hour * 24)
err = validator.ValidateFieldByTag(t, "gt")
c.Assert(err, IsNil)
t2 := time.Now().UTC()
err = validator.ValidateFieldByTag(t2, "gt")
c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "gt")
type Test struct {
Now *time.Time `validate:"gt"`
}
s := &Test{
Now: &t,
}
errs := validator.ValidateStruct(s)
c.Assert(errs, IsNil)
s = &Test{
Now: &t2,
}
errs = validator.ValidateStruct(s)
c.Assert(errs, NotNil)
} }
func (ms *MySuite) TestIsGte(c *C) { func (ms *MySuite) TestIsGte(c *C) {
i := true i := true
c.Assert(func() { validator.ValidateFieldByTag(i, "gte") }, PanicMatches, "Bad field type bool") c.Assert(func() { validator.ValidateFieldByTag(i, "gte") }, PanicMatches, "Bad field type bool")
t := time.Now().UTC()
t = t.Add(time.Hour * 24)
err := validator.ValidateFieldByTag(t, "gte")
c.Assert(err, IsNil)
t2 := time.Now().UTC()
err = validator.ValidateFieldByTag(t2, "gte")
c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "gte")
type Test struct {
Now *time.Time `validate:"gte"`
}
s := &Test{
Now: &t,
}
errs := validator.ValidateStruct(s)
c.Assert(errs, IsNil)
s = &Test{
Now: &t2,
}
errs = validator.ValidateStruct(s)
c.Assert(errs, NotNil)
} }
func (ms *MySuite) TestIsLt(c *C) { func (ms *MySuite) TestIsLt(c *C) {
@ -242,12 +301,72 @@ func (ms *MySuite) TestIsLt(c *C) {
i := true i := true
c.Assert(func() { validator.ValidateFieldByTag(i, "lt") }, PanicMatches, "Bad field type bool") c.Assert(func() { validator.ValidateFieldByTag(i, "lt") }, PanicMatches, "Bad field type bool")
t := time.Now().UTC()
err = validator.ValidateFieldByTag(t, "lt")
c.Assert(err, IsNil)
t2 := time.Now().UTC()
t2 = t2.Add(time.Hour * 24)
err = validator.ValidateFieldByTag(t2, "lt")
c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "lt")
type Test struct {
Now *time.Time `validate:"lt"`
}
s := &Test{
Now: &t,
}
errs := validator.ValidateStruct(s)
c.Assert(errs, IsNil)
s = &Test{
Now: &t2,
}
errs = validator.ValidateStruct(s)
c.Assert(errs, NotNil)
} }
func (ms *MySuite) TestIsLte(c *C) { func (ms *MySuite) TestIsLte(c *C) {
i := true i := true
c.Assert(func() { validator.ValidateFieldByTag(i, "lte") }, PanicMatches, "Bad field type bool") c.Assert(func() { validator.ValidateFieldByTag(i, "lte") }, PanicMatches, "Bad field type bool")
t := time.Now().UTC()
err := validator.ValidateFieldByTag(t, "lte")
c.Assert(err, IsNil)
t2 := time.Now().UTC()
t2 = t2.Add(time.Hour * 24)
err = validator.ValidateFieldByTag(t2, "lte")
c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "lte")
type Test struct {
Now *time.Time `validate:"lte"`
}
s := &Test{
Now: &t,
}
errs := validator.ValidateStruct(s)
c.Assert(errs, IsNil)
s = &Test{
Now: &t2,
}
errs = validator.ValidateStruct(s)
c.Assert(errs, NotNil)
} }
func (ms *MySuite) TestUrl(c *C) { func (ms *MySuite) TestUrl(c *C) {

Loading…
Cancel
Save