Merge pull request #1581 from prometheus/vendorup

vendor: update govalidator
This commit is contained in:
Brian Brazil 2016-04-24 09:56:30 +01:00
commit 816193f254
6 changed files with 136 additions and 36 deletions

View file

@ -42,6 +42,7 @@ func Filter(array []interface{}, iterator ConditionIterator) []interface{}
func Find(array []interface{}, iterator ConditionIterator) interface{} func Find(array []interface{}, iterator ConditionIterator) interface{}
func GetLine(s string, index int) (string, error) func GetLine(s string, index int) (string, error)
func GetLines(s string) []string func GetLines(s string) []string
func IsHost(s string) bool
func InRange(value, left, right float64) bool func InRange(value, left, right float64) bool
func IsASCII(str string) bool func IsASCII(str string) bool
func IsAlpha(str string) bool func IsAlpha(str string) bool
@ -50,6 +51,8 @@ func IsBase64(str string) bool
func IsByteLength(str string, min, max int) bool func IsByteLength(str string, min, max int) bool
func IsCreditCard(str string) bool func IsCreditCard(str string) bool
func IsDataURI(str string) bool func IsDataURI(str string) bool
func IsDialString(str string) bool
func IsDNSName(str string) bool
func IsDivisibleBy(str, num string) bool func IsDivisibleBy(str, num string) bool
func IsEmail(str string) bool func IsEmail(str string) bool
func IsFilePath(str string) (bool, int) func IsFilePath(str string) (bool, int)
@ -80,6 +83,7 @@ func IsNonNegative(value float64) bool
func IsNonPositive(value float64) bool func IsNonPositive(value float64) bool
func IsNull(str string) bool func IsNull(str string) bool
func IsNumeric(str string) bool func IsNumeric(str string) bool
func IsPort(str string) bool
func IsPositive(value float64) bool func IsPositive(value float64) bool
func IsPrintableASCII(str string) bool func IsPrintableASCII(str string) bool
func IsRGBcolor(str string) bool func IsRGBcolor(str string) bool
@ -146,7 +150,7 @@ type User struct {
LastName string LastName string
} }
str, _ := govalidator.ToString(&User{"John", "Juan"}) str := govalidator.ToString(&User{"John", "Juan"})
println(str) println(str)
``` ```
###### Each, Map, Filter, Count for slices ###### Each, Map, Filter, Count for slices
@ -188,12 +192,15 @@ Here is a list of available validators for struct fields (validator - used funct
"base64": IsBase64, "base64": IsBase64,
"creditcard": IsCreditCard, "creditcard": IsCreditCard,
"datauri": IsDataURI, "datauri": IsDataURI,
"dialstring": IsDialString,
"dns": IsDNSName,
"email": IsEmail, "email": IsEmail,
"float": IsFloat, "float": IsFloat,
"fullwidth": IsFullWidth, "fullwidth": IsFullWidth,
"halfwidth": IsHalfWidth, "halfwidth": IsHalfWidth,
"hexadecimal": IsHexadecimal, "hexadecimal": IsHexadecimal,
"hexcolor": IsHexcolor, "hexcolor": IsHexcolor,
"host": IsHost,
"int": IsInt, "int": IsInt,
"ip": IsIP, "ip": IsIP,
"ipv4": IsIPv4, "ipv4": IsIPv4,
@ -208,6 +215,7 @@ Here is a list of available validators for struct fields (validator - used funct
"multibyte": IsMultibyte, "multibyte": IsMultibyte,
"null": IsNull, "null": IsNull,
"numeric": IsNumeric, "numeric": IsNumeric,
"port": IsPort,
"printableascii": IsPrintableASCII, "printableascii": IsPrintableASCII,
"requri": IsRequestURI, "requri": IsRequestURI,
"requrl": IsRequestURL, "requrl": IsRequestURL,
@ -282,4 +290,3 @@ If you do have a contribution for the package feel free to put up a Pull Request
* [Simon ccl1115](https://github.com/ccl1115) * [Simon ccl1115](https://github.com/ccl1115)
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/asaskevich/govalidator/trend.png)](https://bitdeli.com/free "Bitdeli Badge") [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/asaskevich/govalidator/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

View file

@ -15,10 +15,15 @@ func (es Errors) Error() string {
} }
type Error struct { type Error struct {
Name string Name string
Err error Err error
CustomErrorMessageExists bool
} }
func (e Error) Error() string { func (e Error) Error() string {
return e.Name + ": " + e.Err.Error() if e.CustomErrorMessageExists {
return e.Err.Error()
} else {
return e.Name + ": " + e.Err.Error()
}
} }

View file

@ -29,7 +29,8 @@ const (
DataURI string = "^data:.+\\/(.+);base64$" DataURI string = "^data:.+\\/(.+);base64$"
Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$" Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$" Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
URL string = `^((ftp|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$` DNSName string = `^([a-zA-Z0-9]{1}[a-zA-Z0-9_-]{1,62}){1}(\.[a-zA-Z0-9]{1}[a-zA-Z0-9_-]{1,62})*$`
URL string = `^((ftp|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`
SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$`
UnixPath string = `^((?:\/[a-zA-Z0-9\.\:]+(?:_[a-zA-Z0-9\:\.]+)*(?:\-[\:a-zA-Z0-9\.]+)*)+\/?)$` UnixPath string = `^((?:\/[a-zA-Z0-9\.\:]+(?:_[a-zA-Z0-9\:\.]+)*(?:\-[\:a-zA-Z0-9\.]+)*)+\/?)$`
@ -73,6 +74,7 @@ var (
rxDataURI = regexp.MustCompile(DataURI) rxDataURI = regexp.MustCompile(DataURI)
rxLatitude = regexp.MustCompile(Latitude) rxLatitude = regexp.MustCompile(Latitude)
rxLongitude = regexp.MustCompile(Longitude) rxLongitude = regexp.MustCompile(Longitude)
rxDNSName = regexp.MustCompile(DNSName)
rxURL = regexp.MustCompile(URL) rxURL = regexp.MustCompile(URL)
rxSSN = regexp.MustCompile(SSN) rxSSN = regexp.MustCompile(SSN)
rxWinPath = regexp.MustCompile(WinPath) rxWinPath = regexp.MustCompile(WinPath)

View file

@ -46,6 +46,7 @@ var CustomTypeTagMap = map[string]CustomTypeValidator{}
var TagMap = map[string]Validator{ var TagMap = map[string]Validator{
"email": IsEmail, "email": IsEmail,
"url": IsURL, "url": IsURL,
"dialstring": IsDialString,
"requrl": IsRequestURL, "requrl": IsRequestURL,
"requri": IsRequestURI, "requri": IsRequestURI,
"alpha": IsAlpha, "alpha": IsAlpha,
@ -80,8 +81,11 @@ var TagMap = map[string]Validator{
"base64": IsBase64, "base64": IsBase64,
"datauri": IsDataURI, "datauri": IsDataURI,
"ip": IsIP, "ip": IsIP,
"port": IsPort,
"ipv4": IsIPv4, "ipv4": IsIPv4,
"ipv6": IsIPv6, "ipv6": IsIPv6,
"dns": IsDNSName,
"host": IsHost,
"mac": IsMAC, "mac": IsMAC,
"latitude": IsLatitude, "latitude": IsLatitude,
"longitude": IsLongitude, "longitude": IsLongitude,

View file

@ -9,7 +9,9 @@ import (
"reflect" "reflect"
"regexp" "regexp"
"sort" "sort"
"strconv"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
) )
@ -450,11 +452,38 @@ func IsISO3166Alpha3(str string) bool {
return false return false
} }
// IsDNSName will validate the given string as a DNS name
func IsDNSName(str string) bool {
if str == "" || len(strings.Replace(str, ".", "", -1)) > 255 {
// constraints already violated
return false
}
return rxDNSName.MatchString(str)
}
// IsDialString validates the given string for usage with the various Dial() functions
func IsDialString(str string) bool {
if h, p, err := net.SplitHostPort(str); err == nil && h != "" && p != "" && (IsDNSName(h) || IsIP(h)) && IsPort(p) {
return true
}
return false
}
// IsIP checks if a string is either IP version 4 or 6. // IsIP checks if a string is either IP version 4 or 6.
func IsIP(str string) bool { func IsIP(str string) bool {
return net.ParseIP(str) != nil return net.ParseIP(str) != nil
} }
// IsPort checks if a string represents a valid port
func IsPort(str string) bool {
if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 {
return true
}
return false
}
// IsIPv4 check if the string is an IP version 4. // IsIPv4 check if the string is an IP version 4.
func IsIPv4(str string) bool { func IsIPv4(str string) bool {
ip := net.ParseIP(str) ip := net.ParseIP(str)
@ -480,6 +509,11 @@ func IsMAC(str string) bool {
return err == nil return err == nil
} }
// IsHost checks if the string is a valid IP (both v4 and v6) or a valid DNS name
func IsHost(str string) bool {
return IsIP(str) || IsDNSName(str)
}
// IsMongoID check if the string is a valid hex-encoded representation of a MongoDB ObjectId. // IsMongoID check if the string is a valid hex-encoded representation of a MongoDB ObjectId.
func IsMongoID(str string) bool { func IsMongoID(str string) bool {
return rxHexadecimal.MatchString(str) && (len(str) == 24) return rxHexadecimal.MatchString(str) && (len(str) == 24)
@ -614,19 +648,39 @@ func (opts tagOptions) contains(optionName string) bool {
return false return false
} }
func searchOption(limit int, predicate func(counter int) bool) int {
for counter := 0; counter < limit; counter++ {
if predicate(counter) {
return counter
}
}
return -1
}
func checkRequired(v reflect.Value, t reflect.StructField, options tagOptions) (bool, error) { func checkRequired(v reflect.Value, t reflect.StructField, options tagOptions) (bool, error) {
if options.contains("required") { var err error
err := fmt.Errorf("non zero value required") var customErrorMessageExists bool
return false, Error{t.Name, err} requiredIndex := searchOption(len(options), func(index int) bool { return strings.HasPrefix(options[index], "required") })
} else if fieldsRequiredByDefault && !options.contains("optional") { optionalIndex := searchOption(len(options), func(index int) bool { return strings.HasPrefix(options[index], "optional") })
if requiredIndex > -1 {
validationOptions := strings.Split(options[requiredIndex], "~")
if len(validationOptions) == 2 {
err = fmt.Errorf(strings.Split(options[requiredIndex], "~")[1])
customErrorMessageExists = true
} else {
err = fmt.Errorf("non zero value required")
}
return false, Error{t.Name, err, customErrorMessageExists}
} else if fieldsRequiredByDefault && optionalIndex == -1 {
err := fmt.Errorf("All fields are required to at least have one validation defined") err := fmt.Errorf("All fields are required to at least have one validation defined")
return false, Error{t.Name, err} return false, Error{t.Name, err, customErrorMessageExists}
} }
// not required and empty is valid // not required and empty is valid
return true, nil return true, nil
} }
func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) { func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
var customErrorMessageExists bool
if !v.IsValid() { if !v.IsValid() {
return false, nil return false, nil
} }
@ -640,7 +694,7 @@ func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
return true, nil return true, nil
} }
err := fmt.Errorf("All fields are required to at least have one validation defined") err := fmt.Errorf("All fields are required to at least have one validation defined")
return false, Error{t.Name, err} return false, Error{t.Name, err, customErrorMessageExists}
case "-": case "-":
return true, nil return true, nil
} }
@ -648,13 +702,17 @@ func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
options := parseTag(tag) options := parseTag(tag)
for i := range options { for i := range options {
tagOpt := options[i] tagOpt := options[i]
if ok := isValidTag(tagOpt); !ok { tagOptions := strings.Split(tagOpt, "~")
if ok := isValidTag(tagOptions[0]); !ok {
continue continue
} }
if validatefunc, ok := CustomTypeTagMap[tagOpt]; ok { if validatefunc, ok := CustomTypeTagMap[tagOptions[0]]; ok {
options = append(options[:i], options[i+1:]...) // we found our custom validator, so remove it from the options options = append(options[:i], options[i+1:]...) // we found our custom validator, so remove it from the options
if result := validatefunc(v.Interface()); !result { if result := validatefunc(v.Interface()); !result {
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), tagOpt)} if len(tagOptions) == 2 {
return false, Error{t.Name, fmt.Errorf(tagOptions[1]), true}
}
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), tagOptions[0]), false}
} }
return true, nil return true, nil
} }
@ -674,60 +732,81 @@ func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
// for each tag option check the map of validator functions // for each tag option check the map of validator functions
for i := range options { for i := range options {
tagOpt := options[i] tagOpt := options[i]
tagOptions := strings.Split(tagOpt, "~")
negate := false negate := false
customMsgExists := (len(tagOptions) == 2)
// Check wether the tag looks like '!something' or 'something' // Check wether the tag looks like '!something' or 'something'
if len(tagOpt) > 0 && tagOpt[0] == '!' { if len(tagOptions[0]) > 0 && tagOptions[0][0] == '!' {
tagOpt = string(tagOpt[1:]) tagOpt = string(tagOptions[0][1:])
tagOptions[0] = tagOpt
negate = true negate = true
} }
if ok := isValidTag(tagOpt); !ok { if ok := isValidTag(tagOptions[0]); !ok {
err := fmt.Errorf("Unknown Validator %s", tagOpt) err := fmt.Errorf("Unknown Validator %s", tagOptions[0])
return false, Error{t.Name, err} return false, Error{t.Name, err, false}
} }
// Check for param validators // Check for param validators
for key, value := range ParamTagRegexMap { for key, value := range ParamTagRegexMap {
ps := value.FindStringSubmatch(tagOpt) ps := value.FindStringSubmatch(tagOptions[0])
if len(ps) > 0 { if len(ps) > 0 {
if validatefunc, ok := ParamTagMap[key]; ok { if validatefunc, ok := ParamTagMap[key]; ok {
switch v.Kind() { switch v.Kind() {
case reflect.String: case reflect.String:
field := fmt.Sprint(v) // make value into string, then validate with regex field := fmt.Sprint(v) // make value into string, then validate with regex
if result := validatefunc(field, ps[1:]...); !result && !negate || result && negate { if result := validatefunc(field, ps[1:]...); (!result && !negate) || (result && negate) {
var err error var err error
if !negate { if !negate {
err = fmt.Errorf("%s does not validate as %s", field, tagOpt) if customMsgExists {
err = fmt.Errorf(tagOptions[1])
} else {
err = fmt.Errorf("%s does not validate as %s", field, tagOpt)
}
} else { } else {
err = fmt.Errorf("%s does validate as %s", field, tagOpt) if customMsgExists {
err = fmt.Errorf(tagOptions[1])
} else {
err = fmt.Errorf("%s does validate as %s", field, tagOpt)
}
} }
return false, Error{t.Name, err} return false, Error{t.Name, err, customMsgExists}
} }
default: default:
//Not Yet Supported Types (Fail here!) //Not Yet Supported Types (Fail here!)
err := fmt.Errorf("Validator %s doesn't support kind %s", tagOpt, v.Kind()) err := fmt.Errorf("Validator %s doesn't support kind %s", tagOptions[0], v.Kind())
return false, Error{t.Name, err} return false, Error{t.Name, err, false}
} }
} }
} }
} }
if validatefunc, ok := TagMap[tagOpt]; ok { if validatefunc, ok := TagMap[tagOptions[0]]; ok {
switch v.Kind() { switch v.Kind() {
case reflect.String: case reflect.String:
field := fmt.Sprint(v) // make value into string, then validate with regex field := fmt.Sprint(v) // make value into string, then validate with regex
if result := validatefunc(field); !result && !negate || result && negate { if result := validatefunc(field); !result && !negate || result && negate {
var err error var err error
if !negate { if !negate {
err = fmt.Errorf("%s does not validate as %s", field, tagOpt) if customMsgExists {
err = fmt.Errorf(tagOptions[1])
} else {
err = fmt.Errorf("%s does not validate as %s", field, tagOpt)
}
} else { } else {
err = fmt.Errorf("%s does validate as %s", field, tagOpt) if customMsgExists {
err = fmt.Errorf(tagOptions[1])
} else {
err = fmt.Errorf("%s does validate as %s", field, tagOpt)
}
} }
return false, Error{t.Name, err} return false, Error{t.Name, err, customMsgExists}
} }
default: default:
//Not Yet Supported Types (Fail here!) //Not Yet Supported Types (Fail here!)
err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", tagOpt, v.Kind(), v) err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", tagOptions[0], v.Kind(), v)
return false, Error{t.Name, err} return false, Error{t.Name, err, false}
} }
} }
} }

9
vendor/vendor.json vendored
View file

@ -3,9 +3,11 @@
"ignore": "test", "ignore": "test",
"package": [ "package": [
{ {
"checksumSHA1": "DypC2gHBVRhfPqBbsuGYgkrjvOw=",
"origin": "github.com/prometheus/prometheus/vendor/github.com/asaskevich/govalidator",
"path": "github.com/asaskevich/govalidator", "path": "github.com/asaskevich/govalidator",
"revision": "129580890d97de923d9d9aec06cb1aa771812aff", "revision": "5b6e9375cbf581a9008064f7216e816b568d6daa",
"revisionTime": "2015-12-29T23:28:36+03:00" "revisionTime": "2016-04-23T17:31:43Z"
}, },
{ {
"path": "github.com/aws/aws-sdk-go/aws", "path": "github.com/aws/aws-sdk-go/aws",
@ -313,5 +315,6 @@
"revision": "7ad95dd0798a40da1ccdff6dff35fd177b5edf40", "revision": "7ad95dd0798a40da1ccdff6dff35fd177b5edf40",
"revisionTime": "2015-06-24T11:29:02+01:00" "revisionTime": "2015-06-24T11:29:02+01:00"
} }
] ],
"rootPath": "github.com/prometheus/prometheus"
} }