mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Fnlb was moved to its own repo: fnproject/lb (#702)
* Fnlb was moved to its own repo: fnproject/lb * Clean up fnlb leftovers * Newer deps
This commit is contained in:
committed by
Reed Allman
parent
4ffa3d5005
commit
d3be603e54
26
vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md
generated
vendored
Normal file
26
vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
#### Support
|
||||
If you do have a contribution to the package, feel free to create a Pull Request or an Issue.
|
||||
|
||||
#### What to contribute
|
||||
If you don't know what to do, there are some features and functions that need to be done
|
||||
|
||||
- [ ] Refactor code
|
||||
- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check
|
||||
- [ ] Create actual list of contributors and projects that currently using this package
|
||||
- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues)
|
||||
- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions)
|
||||
- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new
|
||||
- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc
|
||||
- [ ] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224)
|
||||
- [ ] Implement fuzzing testing
|
||||
- [ ] Implement some struct/map/array utilities
|
||||
- [ ] Implement map/array validation
|
||||
- [ ] Implement benchmarking
|
||||
- [ ] Implement batch of examples
|
||||
- [ ] Look at forks for new features and fixes
|
||||
|
||||
#### Advice
|
||||
Feel free to create what you want, but keep in mind when you implement new features:
|
||||
- Code must be clear and readable, names of variables/constants clearly describes what they are doing
|
||||
- Public functions must be documented and described in source file and added to README.md to the list of available functions
|
||||
- There are must be unit-tests for any new functions and improvements
|
||||
128
vendor/github.com/asaskevich/govalidator/README.md
generated
vendored
128
vendor/github.com/asaskevich/govalidator/README.md
generated
vendored
@@ -156,6 +156,7 @@ func IsPort(str string) bool
|
||||
func IsPositive(value float64) bool
|
||||
func IsPrintableASCII(str string) bool
|
||||
func IsRFC3339(str string) bool
|
||||
func IsRFC3339WithoutZone(str string) bool
|
||||
func IsRGBcolor(str string) bool
|
||||
func IsRequestURI(rawurl string) bool
|
||||
func IsRequestURL(rawurl string) bool
|
||||
@@ -269,56 +270,57 @@ For completely custom validators (interface-based), see below.
|
||||
|
||||
Here is a list of available validators for struct fields (validator - used function):
|
||||
```go
|
||||
"email": IsEmail,
|
||||
"url": IsURL,
|
||||
"dialstring": IsDialString,
|
||||
"requrl": IsRequestURL,
|
||||
"requri": IsRequestURI,
|
||||
"alpha": IsAlpha,
|
||||
"utfletter": IsUTFLetter,
|
||||
"alphanum": IsAlphanumeric,
|
||||
"utfletternum": IsUTFLetterNumeric,
|
||||
"numeric": IsNumeric,
|
||||
"utfnumeric": IsUTFNumeric,
|
||||
"utfdigit": IsUTFDigit,
|
||||
"hexadecimal": IsHexadecimal,
|
||||
"hexcolor": IsHexcolor,
|
||||
"rgbcolor": IsRGBcolor,
|
||||
"lowercase": IsLowerCase,
|
||||
"uppercase": IsUpperCase,
|
||||
"int": IsInt,
|
||||
"float": IsFloat,
|
||||
"null": IsNull,
|
||||
"uuid": IsUUID,
|
||||
"uuidv3": IsUUIDv3,
|
||||
"uuidv4": IsUUIDv4,
|
||||
"uuidv5": IsUUIDv5,
|
||||
"creditcard": IsCreditCard,
|
||||
"isbn10": IsISBN10,
|
||||
"isbn13": IsISBN13,
|
||||
"json": IsJSON,
|
||||
"multibyte": IsMultibyte,
|
||||
"ascii": IsASCII,
|
||||
"printableascii": IsPrintableASCII,
|
||||
"fullwidth": IsFullWidth,
|
||||
"halfwidth": IsHalfWidth,
|
||||
"variablewidth": IsVariableWidth,
|
||||
"base64": IsBase64,
|
||||
"datauri": IsDataURI,
|
||||
"ip": IsIP,
|
||||
"port": IsPort,
|
||||
"ipv4": IsIPv4,
|
||||
"ipv6": IsIPv6,
|
||||
"dns": IsDNSName,
|
||||
"host": IsHost,
|
||||
"mac": IsMAC,
|
||||
"latitude": IsLatitude,
|
||||
"longitude": IsLongitude,
|
||||
"ssn": IsSSN,
|
||||
"semver": IsSemver,
|
||||
"rfc3339": IsRFC3339,
|
||||
"ISO3166Alpha2": IsISO3166Alpha2,
|
||||
"ISO3166Alpha3": IsISO3166Alpha3,
|
||||
"email": IsEmail,
|
||||
"url": IsURL,
|
||||
"dialstring": IsDialString,
|
||||
"requrl": IsRequestURL,
|
||||
"requri": IsRequestURI,
|
||||
"alpha": IsAlpha,
|
||||
"utfletter": IsUTFLetter,
|
||||
"alphanum": IsAlphanumeric,
|
||||
"utfletternum": IsUTFLetterNumeric,
|
||||
"numeric": IsNumeric,
|
||||
"utfnumeric": IsUTFNumeric,
|
||||
"utfdigit": IsUTFDigit,
|
||||
"hexadecimal": IsHexadecimal,
|
||||
"hexcolor": IsHexcolor,
|
||||
"rgbcolor": IsRGBcolor,
|
||||
"lowercase": IsLowerCase,
|
||||
"uppercase": IsUpperCase,
|
||||
"int": IsInt,
|
||||
"float": IsFloat,
|
||||
"null": IsNull,
|
||||
"uuid": IsUUID,
|
||||
"uuidv3": IsUUIDv3,
|
||||
"uuidv4": IsUUIDv4,
|
||||
"uuidv5": IsUUIDv5,
|
||||
"creditcard": IsCreditCard,
|
||||
"isbn10": IsISBN10,
|
||||
"isbn13": IsISBN13,
|
||||
"json": IsJSON,
|
||||
"multibyte": IsMultibyte,
|
||||
"ascii": IsASCII,
|
||||
"printableascii": IsPrintableASCII,
|
||||
"fullwidth": IsFullWidth,
|
||||
"halfwidth": IsHalfWidth,
|
||||
"variablewidth": IsVariableWidth,
|
||||
"base64": IsBase64,
|
||||
"datauri": IsDataURI,
|
||||
"ip": IsIP,
|
||||
"port": IsPort,
|
||||
"ipv4": IsIPv4,
|
||||
"ipv6": IsIPv6,
|
||||
"dns": IsDNSName,
|
||||
"host": IsHost,
|
||||
"mac": IsMAC,
|
||||
"latitude": IsLatitude,
|
||||
"longitude": IsLongitude,
|
||||
"ssn": IsSSN,
|
||||
"semver": IsSemver,
|
||||
"rfc3339": IsRFC3339,
|
||||
"rfc3339WithoutZone": IsRFC3339WithoutZone,
|
||||
"ISO3166Alpha2": IsISO3166Alpha2,
|
||||
"ISO3166Alpha3": IsISO3166Alpha3,
|
||||
```
|
||||
Validators with parameters
|
||||
|
||||
@@ -409,7 +411,31 @@ Documentation is available here: [godoc.org](https://godoc.org/github.com/asaske
|
||||
Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator).
|
||||
|
||||
#### Support
|
||||
If you do have a contribution for the package feel free to put up a Pull Request or open Issue.
|
||||
If you do have a contribution to the package, feel free to create a Pull Request or an Issue.
|
||||
|
||||
#### What to contribute
|
||||
If you don't know what to do, there are some features and functions that need to be done
|
||||
|
||||
- [ ] Refactor code
|
||||
- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check
|
||||
- [ ] Create actual list of contributors and projects that currently using this package
|
||||
- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues)
|
||||
- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions)
|
||||
- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new
|
||||
- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc
|
||||
- [ ] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224)
|
||||
- [ ] Implement fuzzing testing
|
||||
- [ ] Implement some struct/map/array utilities
|
||||
- [ ] Implement map/array validation
|
||||
- [ ] Implement benchmarking
|
||||
- [ ] Implement batch of examples
|
||||
- [ ] Look at forks for new features and fixes
|
||||
|
||||
#### Advice
|
||||
Feel free to create what you want, but keep in mind when you implement new features:
|
||||
- Code must be clear and readable, names of variables/constants clearly describes what they are doing
|
||||
- Public functions must be documented and described in source file and added to README.md to the list of available functions
|
||||
- There are must be unit-tests for any new functions and improvements
|
||||
|
||||
#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors)
|
||||
* [Daniel Lohse](https://github.com/annismckenzie)
|
||||
|
||||
11
vendor/github.com/asaskevich/govalidator/error.go
generated
vendored
11
vendor/github.com/asaskevich/govalidator/error.go
generated
vendored
@@ -1,5 +1,7 @@
|
||||
package govalidator
|
||||
|
||||
import "strings"
|
||||
|
||||
// Errors is an array of multiple errors and conforms to the error interface.
|
||||
type Errors []error
|
||||
|
||||
@@ -9,11 +11,11 @@ func (es Errors) Errors() []error {
|
||||
}
|
||||
|
||||
func (es Errors) Error() string {
|
||||
var err string
|
||||
var errs []string
|
||||
for _, e := range es {
|
||||
err += e.Error() + ";"
|
||||
errs = append(errs, e.Error())
|
||||
}
|
||||
return err
|
||||
return strings.Join(errs, ";")
|
||||
}
|
||||
|
||||
// Error encapsulates a name, an error and whether there's a custom error message or not.
|
||||
@@ -21,6 +23,9 @@ type Error struct {
|
||||
Name string
|
||||
Err error
|
||||
CustomErrorMessageExists bool
|
||||
|
||||
// Validator indicates the name of the validator that failed
|
||||
Validator string
|
||||
}
|
||||
|
||||
func (e Error) Error() string {
|
||||
|
||||
8
vendor/github.com/asaskevich/govalidator/error_test.go
generated
vendored
8
vendor/github.com/asaskevich/govalidator/error_test.go
generated
vendored
@@ -15,10 +15,10 @@ func TestErrorsToString(t *testing.T) {
|
||||
expected string
|
||||
}{
|
||||
{Errors{}, ""},
|
||||
{Errors{fmt.Errorf("Error 1")}, "Error 1;"},
|
||||
{Errors{fmt.Errorf("Error 1"), fmt.Errorf("Error 2")}, "Error 1;Error 2;"},
|
||||
{Errors{customErr, fmt.Errorf("Error 2")}, "Custom Error Name: stdlib error;Error 2;"},
|
||||
{Errors{fmt.Errorf("Error 123"), customErrWithCustomErrorMessage}, "Error 123;Bad stuff happened;"},
|
||||
{Errors{fmt.Errorf("Error 1")}, "Error 1"},
|
||||
{Errors{fmt.Errorf("Error 1"), fmt.Errorf("Error 2")}, "Error 1;Error 2"},
|
||||
{Errors{customErr, fmt.Errorf("Error 2")}, "Custom Error Name: stdlib error;Error 2"},
|
||||
{Errors{fmt.Errorf("Error 123"), customErrWithCustomErrorMessage}, "Error 123;Bad stuff happened"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := test.param1.Error()
|
||||
|
||||
41
vendor/github.com/asaskevich/govalidator/numerics.go
generated
vendored
41
vendor/github.com/asaskevich/govalidator/numerics.go
generated
vendored
@@ -1,6 +1,9 @@
|
||||
package govalidator
|
||||
|
||||
import "math"
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Abs returns absolute value of number
|
||||
func Abs(value float64) float64 {
|
||||
@@ -39,13 +42,47 @@ func IsNonPositive(value float64) bool {
|
||||
}
|
||||
|
||||
// InRange returns true if value lies between left and right border
|
||||
func InRange(value, left, right float64) bool {
|
||||
func InRangeInt(value, left, right int) bool {
|
||||
if left > right {
|
||||
left, right = right, left
|
||||
}
|
||||
return value >= left && value <= right
|
||||
}
|
||||
|
||||
// InRange returns true if value lies between left and right border
|
||||
func InRangeFloat32(value, left, right float32) bool {
|
||||
if left > right {
|
||||
left, right = right, left
|
||||
}
|
||||
return value >= left && value <= right
|
||||
}
|
||||
|
||||
// InRange returns true if value lies between left and right border
|
||||
func InRangeFloat64(value, left, right float64) bool {
|
||||
if left > right {
|
||||
left, right = right, left
|
||||
}
|
||||
return value >= left && value <= right
|
||||
}
|
||||
|
||||
// InRange returns true if value lies between left and right border, generic type to handle int, float32 or float64, all types must the same type
|
||||
func InRange(value interface{}, left interface{}, right interface{}) bool {
|
||||
|
||||
reflectValue := reflect.TypeOf(value).Kind()
|
||||
reflectLeft := reflect.TypeOf(left).Kind()
|
||||
reflectRight := reflect.TypeOf(right).Kind()
|
||||
|
||||
if reflectValue == reflect.Int && reflectLeft == reflect.Int && reflectRight == reflect.Int {
|
||||
return InRangeInt(value.(int), left.(int), right.(int))
|
||||
} else if reflectValue == reflect.Float32 && reflectLeft == reflect.Float32 && reflectRight == reflect.Float32 {
|
||||
return InRangeFloat32(value.(float32), left.(float32), right.(float32))
|
||||
} else if reflectValue == reflect.Float64 && reflectLeft == reflect.Float64 && reflectRight == reflect.Float64 {
|
||||
return InRangeFloat64(value.(float64), left.(float64), right.(float64))
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsWhole returns true if value is whole number
|
||||
func IsWhole(value float64) bool {
|
||||
return math.Remainder(value, 1) == 0
|
||||
|
||||
147
vendor/github.com/asaskevich/govalidator/numerics_test.go
generated
vendored
147
vendor/github.com/asaskevich/govalidator/numerics_test.go
generated
vendored
@@ -177,7 +177,60 @@ func TestIsNatural(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestInRange(t *testing.T) {
|
||||
|
||||
func TestInRangeInt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var tests = []struct {
|
||||
param int
|
||||
left int
|
||||
right int
|
||||
expected bool
|
||||
}{
|
||||
{0, 0, 0, true},
|
||||
{1, 0, 0, false},
|
||||
{-1, 0, 0, false},
|
||||
{0, -1, 1, true},
|
||||
{0, 0, 1, true},
|
||||
{0, -1, 0, true},
|
||||
{0, 0, -1, true},
|
||||
{0, 10, 5, false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := InRangeInt(test.param, test.left, test.right)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInRangeFloat32(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var tests = []struct {
|
||||
param float32
|
||||
left float32
|
||||
right float32
|
||||
expected bool
|
||||
}{
|
||||
{0, 0, 0, true},
|
||||
{1, 0, 0, false},
|
||||
{-1, 0, 0, false},
|
||||
{0, -1, 1, true},
|
||||
{0, 0, 1, true},
|
||||
{0, -1, 0, true},
|
||||
{0, 0, -1, true},
|
||||
{0, 10, 5, false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := InRangeFloat32(test.param, test.left, test.right)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected InRangeFloat32(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInRangeFloat64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var tests = []struct {
|
||||
@@ -196,6 +249,98 @@ func TestInRange(t *testing.T) {
|
||||
{0, 10, 5, false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := InRangeFloat64(test.param, test.left, test.right)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected InRangeFloat64(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInRange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var testsInt = []struct {
|
||||
param int
|
||||
left int
|
||||
right int
|
||||
expected bool
|
||||
}{
|
||||
{0, 0, 0, true},
|
||||
{1, 0, 0, false},
|
||||
{-1, 0, 0, false},
|
||||
{0, -1, 1, true},
|
||||
{0, 0, 1, true},
|
||||
{0, -1, 0, true},
|
||||
{0, 0, -1, true},
|
||||
{0, 10, 5, false},
|
||||
}
|
||||
for _, test := range testsInt {
|
||||
actual := InRange(test.param, test.left, test.right)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
var testsFloat32 = []struct {
|
||||
param float32
|
||||
left float32
|
||||
right float32
|
||||
expected bool
|
||||
}{
|
||||
{0, 0, 0, true},
|
||||
{1, 0, 0, false},
|
||||
{-1, 0, 0, false},
|
||||
{0, -1, 1, true},
|
||||
{0, 0, 1, true},
|
||||
{0, -1, 0, true},
|
||||
{0, 0, -1, true},
|
||||
{0, 10, 5, false},
|
||||
}
|
||||
for _, test := range testsFloat32 {
|
||||
actual := InRange(test.param, test.left, test.right)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
var testsFloat64 = []struct {
|
||||
param float64
|
||||
left float64
|
||||
right float64
|
||||
expected bool
|
||||
}{
|
||||
{0, 0, 0, true},
|
||||
{1, 0, 0, false},
|
||||
{-1, 0, 0, false},
|
||||
{0, -1, 1, true},
|
||||
{0, 0, 1, true},
|
||||
{0, -1, 0, true},
|
||||
{0, 0, -1, true},
|
||||
{0, 10, 5, false},
|
||||
}
|
||||
for _, test := range testsFloat64 {
|
||||
actual := InRange(test.param, test.left, test.right)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
var testsTypeMix = []struct {
|
||||
param int
|
||||
left float64
|
||||
right float64
|
||||
expected bool
|
||||
}{
|
||||
{0, 0, 0, false},
|
||||
{1, 0, 0, false},
|
||||
{-1, 0, 0, false},
|
||||
{0, -1, 1, false},
|
||||
{0, 0, 1, false},
|
||||
{0, -1, 0, false},
|
||||
{0, 0, -1, false},
|
||||
{0, 10, 5, false},
|
||||
}
|
||||
for _, test := range testsTypeMix {
|
||||
actual := InRange(test.param, test.left, test.right)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual)
|
||||
|
||||
1
vendor/github.com/asaskevich/govalidator/patterns.go
generated
vendored
1
vendor/github.com/asaskevich/govalidator/patterns.go
generated
vendored
@@ -33,7 +33,6 @@ const (
|
||||
IP string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
|
||||
URLSchema string = `((ftp|tcp|udp|wss?|https?):\/\/)`
|
||||
URLUsername string = `(\S+(:\S*)?@)`
|
||||
Hostname string = ``
|
||||
URLPath string = `((\/|\?|#)[^\s]*)`
|
||||
URLPort string = `(:(\d{1,5}))`
|
||||
URLIP string = `([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]))`
|
||||
|
||||
105
vendor/github.com/asaskevich/govalidator/types.go
generated
vendored
105
vendor/github.com/asaskevich/govalidator/types.go
generated
vendored
@@ -34,6 +34,7 @@ var ParamTagMap = map[string]ParamValidator{
|
||||
"stringlength": StringLength,
|
||||
"matches": StringMatches,
|
||||
"in": isInRaw,
|
||||
"rsapub": IsRsaPub,
|
||||
}
|
||||
|
||||
// ParamTagRegexMap maps param tags to their respective regexes.
|
||||
@@ -44,6 +45,7 @@ var ParamTagRegexMap = map[string]*regexp.Regexp{
|
||||
"stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"),
|
||||
"in": regexp.MustCompile(`^in\((.*)\)`),
|
||||
"matches": regexp.MustCompile(`^matches\((.+)\)$`),
|
||||
"rsapub": regexp.MustCompile("^rsapub\\((\\d+)\\)$"),
|
||||
}
|
||||
|
||||
type customTypeTagMap struct {
|
||||
@@ -72,57 +74,58 @@ var CustomTypeTagMap = &customTypeTagMap{validators: make(map[string]CustomTypeV
|
||||
|
||||
// TagMap is a map of functions, that can be used as tags for ValidateStruct function.
|
||||
var TagMap = map[string]Validator{
|
||||
"email": IsEmail,
|
||||
"url": IsURL,
|
||||
"dialstring": IsDialString,
|
||||
"requrl": IsRequestURL,
|
||||
"requri": IsRequestURI,
|
||||
"alpha": IsAlpha,
|
||||
"utfletter": IsUTFLetter,
|
||||
"alphanum": IsAlphanumeric,
|
||||
"utfletternum": IsUTFLetterNumeric,
|
||||
"numeric": IsNumeric,
|
||||
"utfnumeric": IsUTFNumeric,
|
||||
"utfdigit": IsUTFDigit,
|
||||
"hexadecimal": IsHexadecimal,
|
||||
"hexcolor": IsHexcolor,
|
||||
"rgbcolor": IsRGBcolor,
|
||||
"lowercase": IsLowerCase,
|
||||
"uppercase": IsUpperCase,
|
||||
"int": IsInt,
|
||||
"float": IsFloat,
|
||||
"null": IsNull,
|
||||
"uuid": IsUUID,
|
||||
"uuidv3": IsUUIDv3,
|
||||
"uuidv4": IsUUIDv4,
|
||||
"uuidv5": IsUUIDv5,
|
||||
"creditcard": IsCreditCard,
|
||||
"isbn10": IsISBN10,
|
||||
"isbn13": IsISBN13,
|
||||
"json": IsJSON,
|
||||
"multibyte": IsMultibyte,
|
||||
"ascii": IsASCII,
|
||||
"printableascii": IsPrintableASCII,
|
||||
"fullwidth": IsFullWidth,
|
||||
"halfwidth": IsHalfWidth,
|
||||
"variablewidth": IsVariableWidth,
|
||||
"base64": IsBase64,
|
||||
"datauri": IsDataURI,
|
||||
"ip": IsIP,
|
||||
"port": IsPort,
|
||||
"ipv4": IsIPv4,
|
||||
"ipv6": IsIPv6,
|
||||
"dns": IsDNSName,
|
||||
"host": IsHost,
|
||||
"mac": IsMAC,
|
||||
"latitude": IsLatitude,
|
||||
"longitude": IsLongitude,
|
||||
"ssn": IsSSN,
|
||||
"semver": IsSemver,
|
||||
"rfc3339": IsRFC3339,
|
||||
"ISO3166Alpha2": IsISO3166Alpha2,
|
||||
"ISO3166Alpha3": IsISO3166Alpha3,
|
||||
"ISO4217": IsISO4217,
|
||||
"email": IsEmail,
|
||||
"url": IsURL,
|
||||
"dialstring": IsDialString,
|
||||
"requrl": IsRequestURL,
|
||||
"requri": IsRequestURI,
|
||||
"alpha": IsAlpha,
|
||||
"utfletter": IsUTFLetter,
|
||||
"alphanum": IsAlphanumeric,
|
||||
"utfletternum": IsUTFLetterNumeric,
|
||||
"numeric": IsNumeric,
|
||||
"utfnumeric": IsUTFNumeric,
|
||||
"utfdigit": IsUTFDigit,
|
||||
"hexadecimal": IsHexadecimal,
|
||||
"hexcolor": IsHexcolor,
|
||||
"rgbcolor": IsRGBcolor,
|
||||
"lowercase": IsLowerCase,
|
||||
"uppercase": IsUpperCase,
|
||||
"int": IsInt,
|
||||
"float": IsFloat,
|
||||
"null": IsNull,
|
||||
"uuid": IsUUID,
|
||||
"uuidv3": IsUUIDv3,
|
||||
"uuidv4": IsUUIDv4,
|
||||
"uuidv5": IsUUIDv5,
|
||||
"creditcard": IsCreditCard,
|
||||
"isbn10": IsISBN10,
|
||||
"isbn13": IsISBN13,
|
||||
"json": IsJSON,
|
||||
"multibyte": IsMultibyte,
|
||||
"ascii": IsASCII,
|
||||
"printableascii": IsPrintableASCII,
|
||||
"fullwidth": IsFullWidth,
|
||||
"halfwidth": IsHalfWidth,
|
||||
"variablewidth": IsVariableWidth,
|
||||
"base64": IsBase64,
|
||||
"datauri": IsDataURI,
|
||||
"ip": IsIP,
|
||||
"port": IsPort,
|
||||
"ipv4": IsIPv4,
|
||||
"ipv6": IsIPv6,
|
||||
"dns": IsDNSName,
|
||||
"host": IsHost,
|
||||
"mac": IsMAC,
|
||||
"latitude": IsLatitude,
|
||||
"longitude": IsLongitude,
|
||||
"ssn": IsSSN,
|
||||
"semver": IsSemver,
|
||||
"rfc3339": IsRFC3339,
|
||||
"rfc3339WithoutZone": IsRFC3339WithoutZone,
|
||||
"ISO3166Alpha2": IsISO3166Alpha2,
|
||||
"ISO3166Alpha3": IsISO3166Alpha3,
|
||||
"ISO4217": IsISO4217,
|
||||
}
|
||||
|
||||
// ISO3166Entry stores country codes
|
||||
|
||||
2
vendor/github.com/asaskevich/govalidator/utils.go
generated
vendored
2
vendor/github.com/asaskevich/govalidator/utils.go
generated
vendored
@@ -108,7 +108,7 @@ func CamelCaseToUnderscore(str string) string {
|
||||
var output []rune
|
||||
var segment []rune
|
||||
for _, r := range str {
|
||||
if !unicode.IsLower(r) {
|
||||
if !unicode.IsLower(r) && string(r) != "_" {
|
||||
output = addSegment(output, segment)
|
||||
segment = nil
|
||||
}
|
||||
|
||||
1
vendor/github.com/asaskevich/govalidator/utils_test.go
generated
vendored
1
vendor/github.com/asaskevich/govalidator/utils_test.go
generated
vendored
@@ -269,6 +269,7 @@ func TestCamelCaseToUnderscore(t *testing.T) {
|
||||
{"MyFunc", "my_func"},
|
||||
{"ABC", "a_b_c"},
|
||||
{"1B", "1_b"},
|
||||
{"foo_bar", "foo_bar"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := CamelCaseToUnderscore(test.param)
|
||||
|
||||
169
vendor/github.com/asaskevich/govalidator/validator.go
generated
vendored
169
vendor/github.com/asaskevich/govalidator/validator.go
generated
vendored
@@ -2,8 +2,14 @@
|
||||
package govalidator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/url"
|
||||
"reflect"
|
||||
@@ -20,10 +26,12 @@ var (
|
||||
fieldsRequiredByDefault bool
|
||||
notNumberRegexp = regexp.MustCompile("[^0-9]+")
|
||||
whiteSpacesAndMinus = regexp.MustCompile("[\\s-]+")
|
||||
paramsRegexp = regexp.MustCompile("\\(.*\\)$")
|
||||
)
|
||||
|
||||
const maxURLRuneCount = 2083
|
||||
const minURLRuneCount = 3
|
||||
const RF3339WithoutZone = "2006-01-02T15:04:05"
|
||||
|
||||
// SetFieldsRequiredByDefault causes validation to fail when struct fields
|
||||
// do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`).
|
||||
@@ -54,7 +62,13 @@ func IsURL(str string) bool {
|
||||
if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") {
|
||||
return false
|
||||
}
|
||||
u, err := url.Parse(str)
|
||||
strTemp := str
|
||||
if strings.Index(str, ":") >= 0 && strings.Index(str, "://") == -1 {
|
||||
// support no indicated urlscheme but with colon for port number
|
||||
// http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
|
||||
strTemp = "http://" + str
|
||||
}
|
||||
u, err := url.Parse(strTemp)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@@ -65,7 +79,6 @@ func IsURL(str string) bool {
|
||||
return false
|
||||
}
|
||||
return rxURL.MatchString(str)
|
||||
|
||||
}
|
||||
|
||||
// IsRequestURL check if the string rawurl, assuming
|
||||
@@ -486,6 +499,33 @@ func IsDNSName(str string) bool {
|
||||
return !IsIP(str) && rxDNSName.MatchString(str)
|
||||
}
|
||||
|
||||
// IsHash checks if a string is a hash of type algorithm.
|
||||
// Algorithm is one of ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']
|
||||
func IsHash(str string, algorithm string) bool {
|
||||
len := "0"
|
||||
algo := strings.ToLower(algorithm)
|
||||
|
||||
if algo == "crc32" || algo == "crc32b" {
|
||||
len = "8"
|
||||
} else if algo == "md5" || algo == "md4" || algo == "ripemd128" || algo == "tiger128" {
|
||||
len = "32"
|
||||
} else if algo == "sha1" || algo == "ripemd160" || algo == "tiger160" {
|
||||
len = "40"
|
||||
} else if algo == "tiger192" {
|
||||
len = "48"
|
||||
} else if algo == "sha256" {
|
||||
len = "64"
|
||||
} else if algo == "sha384" {
|
||||
len = "96"
|
||||
} else if algo == "sha512" {
|
||||
len = "128"
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
||||
return Matches(str, "^[a-f0-9]{" + len + "}$")
|
||||
}
|
||||
|
||||
// IsDialString validates the given string for usage with the various Dial() functions
|
||||
func IsDialString(str string) bool {
|
||||
|
||||
@@ -560,6 +600,40 @@ func IsLongitude(str string) bool {
|
||||
return rxLongitude.MatchString(str)
|
||||
}
|
||||
|
||||
// IsRsaPublicKey check if a string is valid public key with provided length
|
||||
func IsRsaPublicKey(str string, keylen int) bool {
|
||||
bb := bytes.NewBufferString(str)
|
||||
pemBytes, err := ioutil.ReadAll(bb)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
block, _ := pem.Decode(pemBytes)
|
||||
if block != nil && block.Type != "PUBLIC KEY" {
|
||||
return false
|
||||
}
|
||||
var der []byte
|
||||
|
||||
if block != nil {
|
||||
der = block.Bytes
|
||||
} else {
|
||||
der, err = base64.StdEncoding.DecodeString(str)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
key, err := x509.ParsePKIXPublicKey(der)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pubkey, ok := key.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
bitlen := len(pubkey.N.Bytes()) * 8
|
||||
return bitlen == int(keylen)
|
||||
}
|
||||
|
||||
func toJSONName(tag string) string {
|
||||
if tag == "" {
|
||||
return ""
|
||||
@@ -568,7 +642,16 @@ func toJSONName(tag string) string {
|
||||
// JSON name always comes first. If there's no options then split[0] is
|
||||
// JSON name, if JSON name is not set, then split[0] is an empty string.
|
||||
split := strings.SplitN(tag, ",", 2)
|
||||
return split[0]
|
||||
|
||||
name := split[0]
|
||||
|
||||
// However it is possible that the field is skipped when
|
||||
// (de-)serializing from/to JSON, in which case assume that there is no
|
||||
// tag name to use
|
||||
if name == "-" {
|
||||
return ""
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// ValidateStruct use tags for fields.
|
||||
@@ -595,7 +678,7 @@ func ValidateStruct(s interface{}) (bool, error) {
|
||||
continue // Private field
|
||||
}
|
||||
structResult := true
|
||||
if valueField.Kind() == reflect.Struct {
|
||||
if valueField.Kind() == reflect.Struct && typeField.Tag.Get(tagName) != "-" {
|
||||
var err error
|
||||
structResult, err = ValidateStruct(valueField.Interface())
|
||||
if err != nil {
|
||||
@@ -613,6 +696,14 @@ func ValidateStruct(s interface{}) (bool, error) {
|
||||
jsonError.Name = jsonTag
|
||||
err2 = jsonError
|
||||
case Errors:
|
||||
for i2, err3 := range jsonError {
|
||||
switch customErr := err3.(type) {
|
||||
case Error:
|
||||
customErr.Name = jsonTag
|
||||
jsonError[i2] = customErr
|
||||
}
|
||||
}
|
||||
|
||||
err2 = jsonError
|
||||
}
|
||||
}
|
||||
@@ -630,8 +721,11 @@ func ValidateStruct(s interface{}) (bool, error) {
|
||||
// parseTagIntoMap parses a struct tag `valid:required~Some error message,length(2|3)` into map[string]string{"required": "Some error message", "length(2|3)": ""}
|
||||
func parseTagIntoMap(tag string) tagOptionsMap {
|
||||
optionsMap := make(tagOptionsMap)
|
||||
options := strings.SplitN(tag, ",", -1)
|
||||
options := strings.Split(tag, ",")
|
||||
|
||||
for _, option := range options {
|
||||
option = strings.TrimSpace(option)
|
||||
|
||||
validationOptions := strings.Split(option, "~")
|
||||
if !isValidTag(validationOptions[0]) {
|
||||
continue
|
||||
@@ -688,6 +782,11 @@ func IsRFC3339(str string) bool {
|
||||
return IsTime(str, time.RFC3339)
|
||||
}
|
||||
|
||||
// IsRFC3339WithoutZone check if string is valid timestamp value according to RFC3339 which excludes the timezone.
|
||||
func IsRFC3339WithoutZone(str string) bool {
|
||||
return IsTime(str, RF3339WithoutZone)
|
||||
}
|
||||
|
||||
// IsISO4217 check if string is valid ISO currency code
|
||||
func IsISO4217(str string) bool {
|
||||
for _, currency := range ISO4217List {
|
||||
@@ -716,6 +815,17 @@ func RuneLength(str string, params ...string) bool {
|
||||
return StringLength(str, params...)
|
||||
}
|
||||
|
||||
// IsRsaPub check whether string is valid RSA key
|
||||
// Alias for IsRsaPublicKey
|
||||
func IsRsaPub(str string, params ...string) bool {
|
||||
if len(params) == 1 {
|
||||
len, _ := ToInt(params[0])
|
||||
return IsRsaPublicKey(str, int(len))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// StringMatches checks if a string matches a given pattern.
|
||||
func StringMatches(s string, params ...string) bool {
|
||||
if len(params) == 1 {
|
||||
@@ -776,11 +886,11 @@ func IsIn(str string, params ...string) bool {
|
||||
func checkRequired(v reflect.Value, t reflect.StructField, options tagOptionsMap) (bool, error) {
|
||||
if requiredOption, isRequired := options["required"]; isRequired {
|
||||
if len(requiredOption) > 0 {
|
||||
return false, Error{t.Name, fmt.Errorf(requiredOption), true}
|
||||
return false, Error{t.Name, fmt.Errorf(requiredOption), true, "required"}
|
||||
}
|
||||
return false, Error{t.Name, fmt.Errorf("non zero value required"), false}
|
||||
return false, Error{t.Name, fmt.Errorf("non zero value required"), false, "required"}
|
||||
} else if _, isOptional := options["optional"]; fieldsRequiredByDefault && !isOptional {
|
||||
return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false}
|
||||
return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false, "required"}
|
||||
}
|
||||
// not required and empty is valid
|
||||
return true, nil
|
||||
@@ -799,7 +909,7 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options
|
||||
if !fieldsRequiredByDefault {
|
||||
return true, nil
|
||||
}
|
||||
return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false}
|
||||
return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false, "required"}
|
||||
case "-":
|
||||
return true, nil
|
||||
}
|
||||
@@ -822,10 +932,10 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options
|
||||
|
||||
if result := validatefunc(v.Interface(), o.Interface()); !result {
|
||||
if len(customErrorMessage) > 0 {
|
||||
customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf(customErrorMessage), CustomErrorMessageExists: true})
|
||||
customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf(customErrorMessage), CustomErrorMessageExists: true, Validator: stripParams(validatorName)})
|
||||
continue
|
||||
}
|
||||
customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), validatorName), CustomErrorMessageExists: false})
|
||||
customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), validatorName), CustomErrorMessageExists: false, Validator: stripParams(validatorName)})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -844,7 +954,7 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options
|
||||
for validator := range options {
|
||||
isValid = false
|
||||
resultErr = Error{t.Name, fmt.Errorf(
|
||||
"The following validator is invalid or can't be applied to the field: %q", validator), false}
|
||||
"The following validator is invalid or can't be applied to the field: %q", validator), false, stripParams(validator)}
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -888,16 +998,16 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options
|
||||
field := fmt.Sprint(v) // make value into string, then validate with regex
|
||||
if result := validatefunc(field, ps[1:]...); (!result && !negate) || (result && negate) {
|
||||
if customMsgExists {
|
||||
return false, Error{t.Name, fmt.Errorf(customErrorMessage), customMsgExists}
|
||||
return false, Error{t.Name, fmt.Errorf(customErrorMessage), customMsgExists, stripParams(validatorSpec)}
|
||||
}
|
||||
if negate {
|
||||
return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists}
|
||||
return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec)}
|
||||
}
|
||||
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists}
|
||||
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec)}
|
||||
}
|
||||
default:
|
||||
// type not yet supported, fail
|
||||
return false, Error{t.Name, fmt.Errorf("Validator %s doesn't support kind %s", validator, v.Kind()), false}
|
||||
return false, Error{t.Name, fmt.Errorf("Validator %s doesn't support kind %s", validator, v.Kind()), false, stripParams(validatorSpec)}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,17 +1019,17 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options
|
||||
field := fmt.Sprint(v) // make value into string, then validate with regex
|
||||
if result := validatefunc(field); !result && !negate || result && negate {
|
||||
if customMsgExists {
|
||||
return false, Error{t.Name, fmt.Errorf(customErrorMessage), customMsgExists}
|
||||
return false, Error{t.Name, fmt.Errorf(customErrorMessage), customMsgExists, stripParams(validatorSpec)}
|
||||
}
|
||||
if negate {
|
||||
return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists}
|
||||
return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec)}
|
||||
}
|
||||
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists}
|
||||
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec)}
|
||||
}
|
||||
default:
|
||||
//Not Yet Supported Types (Fail here!)
|
||||
err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", validator, v.Kind(), v)
|
||||
return false, Error{t.Name, err, false}
|
||||
return false, Error{t.Name, err, false, stripParams(validatorSpec)}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -933,9 +1043,18 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options
|
||||
sort.Sort(sv)
|
||||
result := true
|
||||
for _, k := range sv {
|
||||
resultItem, err := ValidateStruct(v.MapIndex(k).Interface())
|
||||
if err != nil {
|
||||
return false, err
|
||||
var resultItem bool
|
||||
var err error
|
||||
if v.MapIndex(k).Kind() != reflect.Struct {
|
||||
resultItem, err = typeCheck(v.MapIndex(k), t, o, options)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
} else {
|
||||
resultItem, err = ValidateStruct(v.MapIndex(k).Interface())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
result = result && resultItem
|
||||
}
|
||||
@@ -978,6 +1097,10 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options
|
||||
}
|
||||
}
|
||||
|
||||
func stripParams(validatorString string) string {
|
||||
return paramsRegexp.ReplaceAllString(validatorString, "")
|
||||
}
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.String, reflect.Array:
|
||||
|
||||
192
vendor/github.com/asaskevich/govalidator/validator_test.go
generated
vendored
192
vendor/github.com/asaskevich/govalidator/validator_test.go
generated
vendored
@@ -536,6 +536,37 @@ func TestIsInt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestIsHash(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var tests = []struct {
|
||||
param string
|
||||
algo string
|
||||
expected bool
|
||||
}{
|
||||
{"3ca25ae354e192b26879f651a51d92aa8a34d8d3", "sha1", true},
|
||||
{"3ca25ae354e192b26879f651a51d34d8d3", "sha1", false},
|
||||
{"3ca25ae354e192b26879f651a51d92aa8a34d8d3", "Tiger160", true},
|
||||
{"3ca25ae354e192b26879f651a51d34d8d3", "ripemd160", false},
|
||||
{"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898c", "sha256", true},
|
||||
{"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha256", false},
|
||||
{"bf547c3fc5841a377eb1519c2890344dbab15c40ae4150b4b34443d2212e5b04aa9d58865bf03d8ae27840fef430b891", "sha384", true},
|
||||
{"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha384", false},
|
||||
{"45bc5fa8cb45ee408c04b6269e9f1e1c17090c5ce26ffeeda2af097735b29953ce547e40ff3ad0d120e5361cc5f9cee35ea91ecd4077f3f589b4d439168f91b9", "sha512", true},
|
||||
{"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha512", false},
|
||||
{"46fc0125a148788a3ac1d649566fc04eb84a746f1a6e4fa7", "tiger192", true},
|
||||
{"46fc0125a148788a3ac1d649566fc04eb84a746f1a6$$%@^", "TIGER192", false},
|
||||
{"46fc0125a148788a3ac1d649566fc04eb84a746f1a6$$%@^", "SOMEHASH", false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := IsHash(test.param, test.algo)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected IsHash(%q, %q) to be %v, got %v", test.param, test.algo, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEmail(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -633,6 +664,7 @@ func TestIsURL(t *testing.T) {
|
||||
{"https://pbs.twimg.com/profile_images/560826135676588032/j8fWrmYY_normal.jpeg", true},
|
||||
// according to #125
|
||||
{"http://prometheus-alertmanager.service.q:9093", true},
|
||||
{"aio1_alertmanager_container-63376c45:9093", true},
|
||||
{"https://www.logn-123-123.url.with.sigle.letter.d:12345/url/path/foo?bar=zzz#user", true},
|
||||
{"http://me.example.com", true},
|
||||
{"http://www.me.example.com", true},
|
||||
@@ -661,6 +693,10 @@ func TestIsURL(t *testing.T) {
|
||||
{"foo_bar.example.com", true},
|
||||
{"foo_bar_fizz_buzz.example.com", true},
|
||||
{"http://hello_world.example.com", true},
|
||||
// According to #212
|
||||
{"foo_bar-fizz-buzz:1313", true},
|
||||
{"foo_bar-fizz-buzz:13:13", false},
|
||||
{"foo_bar-fizz-buzz://1313", false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := IsURL(test.param)
|
||||
@@ -980,6 +1016,7 @@ func TestIsMultibyte(t *testing.T) {
|
||||
{"test@example.com", true},
|
||||
{"1234abcDExyz", true},
|
||||
{"カタカナ", true},
|
||||
{"", true},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := IsMultibyte(test.param)
|
||||
@@ -1850,6 +1887,13 @@ func TestIsTime(t *testing.T) {
|
||||
{"2016-12-31T11:00:00.05Z", time.RFC3339, true},
|
||||
{"2016-12-31T11:00:00.05-01:00", time.RFC3339, true},
|
||||
{"2016-12-31T11:00:00.05+01:00", time.RFC3339, true},
|
||||
{"2016-12-31T11:00:00", RF3339WithoutZone, true},
|
||||
{"2016-12-31T11:00:00Z", RF3339WithoutZone, false},
|
||||
{"2016-12-31T11:00:00+01:00", RF3339WithoutZone, false},
|
||||
{"2016-12-31T11:00:00-01:00", RF3339WithoutZone, false},
|
||||
{"2016-12-31T11:00:00.05Z", RF3339WithoutZone, false},
|
||||
{"2016-12-31T11:00:00.05-01:00", RF3339WithoutZone, false},
|
||||
{"2016-12-31T11:00:00.05+01:00", RF3339WithoutZone, false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := IsTime(test.param, test.format)
|
||||
@@ -2162,7 +2206,7 @@ func TestInvalidValidator(t *testing.T) {
|
||||
|
||||
invalidStruct := InvalidStruct{1}
|
||||
if valid, err := ValidateStruct(&invalidStruct); valid || err == nil ||
|
||||
err.Error() != `Field: The following validator is invalid or can't be applied to the field: "someInvalidValidator";` {
|
||||
err.Error() != `Field: The following validator is invalid or can't be applied to the field: "someInvalidValidator"` {
|
||||
t.Errorf("Got an unexpected result for struct with invalid validator: %t %s", valid, err)
|
||||
}
|
||||
}
|
||||
@@ -2184,12 +2228,12 @@ func TestCustomValidator(t *testing.T) {
|
||||
t.Errorf("Got an unexpected result for struct with custom always true validator: %t %s", valid, err)
|
||||
}
|
||||
|
||||
if valid, err := ValidateStruct(&InvalidStruct{Field: 1}); valid || err == nil || err.Error() != "Custom validator error;;" {
|
||||
if valid, err := ValidateStruct(&InvalidStruct{Field: 1}); valid || err == nil || err.Error() != "Custom validator error" {
|
||||
t.Errorf("Got an unexpected result for struct with custom always false validator: %t %s", valid, err)
|
||||
}
|
||||
|
||||
mixedStruct := StructWithCustomAndBuiltinValidator{}
|
||||
if valid, err := ValidateStruct(&mixedStruct); valid || err == nil || err.Error() != "Field: non zero value required;" {
|
||||
if valid, err := ValidateStruct(&mixedStruct); valid || err == nil || err.Error() != "Field: non zero value required" {
|
||||
t.Errorf("Got an unexpected result for invalid struct with custom and built-in validators: %t %s", valid, err)
|
||||
}
|
||||
|
||||
@@ -2522,6 +2566,8 @@ func TestValidateStruct(t *testing.T) {
|
||||
type testByteArray [8]byte
|
||||
type testByteMap map[byte]byte
|
||||
type testByteSlice []byte
|
||||
type testStringStringMap map[string]string
|
||||
type testStringIntMap map[string]int
|
||||
|
||||
func TestRequired(t *testing.T) {
|
||||
|
||||
@@ -2606,6 +2652,22 @@ func TestRequired(t *testing.T) {
|
||||
}{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
struct {
|
||||
TestStringStringMap testStringStringMap `valid:"required"`
|
||||
}{
|
||||
testStringStringMap{"test": "test"},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
struct {
|
||||
TestIntMap testStringIntMap `valid:"required"`
|
||||
}{
|
||||
testStringIntMap{"test": 42},
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual, err := ValidateStruct(test.param)
|
||||
@@ -2693,7 +2755,7 @@ func TestErrorsByField(t *testing.T) {
|
||||
{"CustomField", "An error occurred"},
|
||||
}
|
||||
|
||||
err = Error{"CustomField", fmt.Errorf("An error occurred"), false}
|
||||
err = Error{"CustomField", fmt.Errorf("An error occurred"), false, "hello"}
|
||||
errs = ErrorsByField(err)
|
||||
|
||||
if len(errs) != 1 {
|
||||
@@ -2838,10 +2900,11 @@ func TestOptionalCustomValidators(t *testing.T) {
|
||||
func TestJSONValidator(t *testing.T) {
|
||||
|
||||
var val struct {
|
||||
WithJSONName string `json:"with_json_name" valid:"-,required"`
|
||||
WithoutJSONName string `valid:"-,required"`
|
||||
WithJSONOmit string `json:"with_other_json_name,omitempty" valid:"-,required"`
|
||||
WithJSONOption string `json:",omitempty" valid:"-,required"`
|
||||
WithJSONName string `json:"with_json_name" valid:"-,required"`
|
||||
WithoutJSONName string `valid:"-,required"`
|
||||
WithJSONOmit string `json:"with_other_json_name,omitempty" valid:"-,required"`
|
||||
WithJSONOption string `json:",omitempty" valid:"-,required"`
|
||||
WithEmptyJSONName string `json:"-" valid:"-,required"`
|
||||
}
|
||||
|
||||
_, err := ValidateStruct(val)
|
||||
@@ -2861,4 +2924,117 @@ func TestJSONValidator(t *testing.T) {
|
||||
if Contains(err.Error(), "omitempty") {
|
||||
t.Errorf("Expected error message to not contain ',omitempty' but actual error is: %s", err.Error())
|
||||
}
|
||||
|
||||
if !Contains(err.Error(), "WithEmptyJSONName") {
|
||||
t.Errorf("Expected error message to contain WithEmptyJSONName but actual error is: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatorIncludedInError(t *testing.T) {
|
||||
post := Post{
|
||||
Title: "",
|
||||
Message: "👍",
|
||||
AuthorIP: "xyz",
|
||||
}
|
||||
|
||||
validatorMap := map[string]string{
|
||||
"Title": "required",
|
||||
"Message": "ascii",
|
||||
"AuthorIP": "ipv4",
|
||||
}
|
||||
|
||||
ok, errors := ValidateStruct(post)
|
||||
if ok {
|
||||
t.Errorf("expected validation to fail %v", ok)
|
||||
}
|
||||
|
||||
for _, e := range errors.(Errors) {
|
||||
casted := e.(Error)
|
||||
if validatorMap[casted.Name] != casted.Validator {
|
||||
t.Errorf("expected validator for %s to be %s, but was %s", casted.Name, validatorMap[casted.Name], casted.Validator)
|
||||
}
|
||||
}
|
||||
|
||||
// check to make sure that validators with arguments (like length(1|10)) don't include the arguments
|
||||
// in the validator name
|
||||
message := MessageWithSeveralFieldsStruct{
|
||||
Title: "",
|
||||
Body: "asdfasdfasdfasdfasdf",
|
||||
}
|
||||
|
||||
validatorMap = map[string]string{
|
||||
"Title": "length",
|
||||
"Body": "length",
|
||||
}
|
||||
|
||||
ok, errors = ValidateStruct(message)
|
||||
if ok {
|
||||
t.Errorf("expected validation to fail, %v", ok)
|
||||
}
|
||||
|
||||
for _, e := range errors.(Errors) {
|
||||
casted := e.(Error)
|
||||
if validatorMap[casted.Name] != casted.Validator {
|
||||
t.Errorf("expected validator for %s to be %s, but was %s", casted.Name, validatorMap[casted.Name], casted.Validator)
|
||||
}
|
||||
}
|
||||
|
||||
// make sure validators with custom messages don't show up in the validator string
|
||||
type CustomMessage struct {
|
||||
Text string `valid:"length(1|10)~Custom message"`
|
||||
}
|
||||
cs := CustomMessage{Text: "asdfasdfasdfasdf"}
|
||||
|
||||
ok, errors = ValidateStruct(&cs)
|
||||
if ok {
|
||||
t.Errorf("expected validation to fail, %v", ok)
|
||||
}
|
||||
|
||||
validator := errors.(Errors)[0].(Error).Validator
|
||||
if validator != "length" {
|
||||
t.Errorf("expected validator for Text to be length, but was %s", validator)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIsRsaPublicKey(t *testing.T) {
|
||||
var tests = []struct {
|
||||
rsastr string
|
||||
keylen int
|
||||
expected bool
|
||||
}{
|
||||
{`fubar`, 2048, false},
|
||||
{`MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuu
|
||||
XwKYLq0DKUE3t/HHsNdowfD9+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9BmMEcI3uoKbeXCbJRI
|
||||
HoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzTUmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZ
|
||||
B7ucimFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUvbQIDAQAB`, 2048, true},
|
||||
{`MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuu
|
||||
XwKYLq0DKUE3t/HHsNdowfD9+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9BmMEcI3uoKbeXCbJRI
|
||||
HoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzTUmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZ
|
||||
B7ucimFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUvbQIDAQAB`, 1024, false},
|
||||
{`-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7
|
||||
x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuuXwKYLq0DKUE3t/HHsNdowfD9
|
||||
+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9
|
||||
BmMEcI3uoKbeXCbJRIHoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzT
|
||||
UmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZB7uc
|
||||
imFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUv
|
||||
bQIDAQAB
|
||||
-----END PUBLIC KEY-----`, 2048, true},
|
||||
{`-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7
|
||||
x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuuXwKYLq0DKUE3t/HHsNdowfD9
|
||||
+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9
|
||||
BmMEcI3uoKbeXCbJRIHoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzT
|
||||
UmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZB7uc
|
||||
imFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUv
|
||||
bQIDAQAB
|
||||
-----END PUBLIC KEY-----`, 4096, false},
|
||||
}
|
||||
for i, test := range tests {
|
||||
actual := IsRsaPublicKey(test.rsastr, test.keylen)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Expected TestIsRsaPublicKey(%d, %d) to be %v, got %v", i, test.keylen, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user