mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 18:51:03 +01:00
182 lines
4.5 KiB
Go
182 lines
4.5 KiB
Go
|
package errors
|
||
|
|
||
|
import (
|
||
|
"math"
|
||
|
"regexp"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// AsValidationErrors reports wheether the given "err" is a type of validation error(s).
|
||
|
func AsValidationErrors(err error) (ValidationErrors, bool) {
|
||
|
if err == nil {
|
||
|
return nil, false
|
||
|
}
|
||
|
|
||
|
switch e := err.(type) {
|
||
|
case ValidationError:
|
||
|
return ValidationErrors{e}, true
|
||
|
case ValidationErrors:
|
||
|
return e, true
|
||
|
case *ValidationErrors:
|
||
|
return *e, true
|
||
|
default:
|
||
|
return nil, false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ValueValidator is a generic interface which can be used to check if the value is valid for insert (or for comparison inside another validation step).
|
||
|
// Useful for enums.
|
||
|
// Should return a non-empty string on validation error, that string is the failure reason.
|
||
|
type ValueValidator interface {
|
||
|
Validate() string
|
||
|
}
|
||
|
|
||
|
// ValidationError describes a field validation error.
|
||
|
type ValidationError struct {
|
||
|
Field string `json:"field" yaml:"Field"`
|
||
|
Value interface{} `json:"value" yaml:"Value"`
|
||
|
Reason string `json:"reason" yaml:"Reason"`
|
||
|
}
|
||
|
|
||
|
// Error completes the standard error interface.
|
||
|
func (e ValidationError) Error() string {
|
||
|
return sprintf("field %q got invalid value of %v: reason: %s", e.Field, e.Value, e.Reason)
|
||
|
}
|
||
|
|
||
|
// ValidationErrors is just a custom type of ValidationError slice.
|
||
|
type ValidationErrors []ValidationError
|
||
|
|
||
|
// Error completes the error interface.
|
||
|
func (e ValidationErrors) Error() string {
|
||
|
var buf strings.Builder
|
||
|
for i, err := range e {
|
||
|
buf.WriteByte('[')
|
||
|
buf.WriteString(strconv.Itoa(i))
|
||
|
buf.WriteByte(']')
|
||
|
buf.WriteByte(' ')
|
||
|
|
||
|
buf.WriteString(err.Error())
|
||
|
|
||
|
if i < len(e)-1 {
|
||
|
buf.WriteByte(',')
|
||
|
buf.WriteByte(' ')
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return buf.String()
|
||
|
}
|
||
|
|
||
|
// Is reports whether the given "err" is a type of validation error or validation errors.
|
||
|
func (e ValidationErrors) Is(err error) bool {
|
||
|
if err == nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch err.(type) {
|
||
|
case ValidationError:
|
||
|
return true
|
||
|
case *ValidationError:
|
||
|
return true
|
||
|
case ValidationErrors:
|
||
|
return true
|
||
|
case *ValidationErrors:
|
||
|
return true
|
||
|
default:
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add is a helper for appending a validation error.
|
||
|
func (e *ValidationErrors) Add(err ValidationError) *ValidationErrors {
|
||
|
if err.Field == "" || err.Reason == "" {
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
*e = append(*e, err)
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
// Join joins an existing Errors to this errors list.
|
||
|
func (e *ValidationErrors) Join(errs ValidationErrors) *ValidationErrors {
|
||
|
*e = append(*e, errs...)
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
// Validate returns the result of the value's Validate method, if exists otherwise
|
||
|
// it adds the field and value to the error list and reports false (invalidated).
|
||
|
// If reason is empty, means that the field is valid, this method will return true.
|
||
|
func (e *ValidationErrors) Validate(field string, value interface{}) bool {
|
||
|
var reason string
|
||
|
|
||
|
if v, ok := value.(ValueValidator); ok {
|
||
|
reason = v.Validate()
|
||
|
}
|
||
|
|
||
|
if reason != "" {
|
||
|
e.Add(ValidationError{
|
||
|
Field: field,
|
||
|
Value: value,
|
||
|
Reason: reason,
|
||
|
})
|
||
|
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// MustBeSatisfiedFunc compares the value with the given "isEqualFunc" function and reports
|
||
|
// if it's valid or not. If it's not valid, a new ValidationError is added to the "e" list.
|
||
|
func (e *ValidationErrors) MustBeSatisfiedFunc(field string, value string, isEqualFunc func(string) bool) bool {
|
||
|
if !isEqualFunc(value) {
|
||
|
e.Add(ValidationError{
|
||
|
Field: field,
|
||
|
Value: value,
|
||
|
Reason: "failed to satisfy constraint",
|
||
|
})
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// MustBeSatisfied compares the value with the given regex and reports
|
||
|
// if it's valid or not. If it's not valid, a new ValidationError is added to the "e" list.
|
||
|
func (e *ValidationErrors) MustBeSatisfied(field string, value string, regex *regexp.Regexp) bool {
|
||
|
return e.MustBeSatisfiedFunc(field, value, regex.MatchString)
|
||
|
}
|
||
|
|
||
|
// MustBeNotEmptyString reports and fails if the given "value" is empty.
|
||
|
func (e *ValidationErrors) MustBeNotEmptyString(field string, value string) bool {
|
||
|
if strings.TrimSpace(value) == "" {
|
||
|
e.Add(ValidationError{
|
||
|
Field: field,
|
||
|
Value: value,
|
||
|
Reason: "must be not an empty string",
|
||
|
})
|
||
|
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// MustBeInRangeString reports whether the "value" is in range of min and max.
|
||
|
func (e *ValidationErrors) MustBeInRangeString(field string, value string, minIncluding, maxIncluding int) bool {
|
||
|
if maxIncluding <= 0 {
|
||
|
maxIncluding = math.MaxInt32
|
||
|
}
|
||
|
|
||
|
if len(value) < minIncluding || len(value) > maxIncluding {
|
||
|
e.Add(ValidationError{
|
||
|
Field: field,
|
||
|
Value: value,
|
||
|
Reason: sprintf("characters length must be between %d and %d", minIncluding, maxIncluding),
|
||
|
})
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|