5849898283
Unit tests functional and coverage back to 100% Add more routes to dictionary, add more credentials, add default port 5554, rename cameradar logs ENV variable, improve unit test readability, remove tmp file
273 lines
7.1 KiB
Go
273 lines
7.1 KiB
Go
package validator
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
|
|
ut "github.com/go-playground/universal-translator"
|
|
)
|
|
|
|
const (
|
|
fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
|
|
)
|
|
|
|
// ValidationErrorsTranslations is the translation return type
|
|
type ValidationErrorsTranslations map[string]string
|
|
|
|
// InvalidValidationError describes an invalid argument passed to
|
|
// `Struct`, `StructExcept`, StructPartial` or `Field`
|
|
type InvalidValidationError struct {
|
|
Type reflect.Type
|
|
}
|
|
|
|
// Error returns InvalidValidationError message
|
|
func (e *InvalidValidationError) Error() string {
|
|
|
|
if e.Type == nil {
|
|
return "validator: (nil)"
|
|
}
|
|
|
|
return "validator: (nil " + e.Type.String() + ")"
|
|
}
|
|
|
|
// ValidationErrors is an array of FieldError's
|
|
// for use in custom error messages post validation.
|
|
type ValidationErrors []FieldError
|
|
|
|
// Error is intended for use in development + debugging and not intended to be a production error message.
|
|
// It allows ValidationErrors to subscribe to the Error interface.
|
|
// All information to create an error message specific to your application is contained within
|
|
// the FieldError found within the ValidationErrors array
|
|
func (ve ValidationErrors) Error() string {
|
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
var fe *fieldError
|
|
|
|
for i := 0; i < len(ve); i++ {
|
|
|
|
fe = ve[i].(*fieldError)
|
|
buff.WriteString(fe.Error())
|
|
buff.WriteString("\n")
|
|
}
|
|
|
|
return strings.TrimSpace(buff.String())
|
|
}
|
|
|
|
// Translate translates all of the ValidationErrors
|
|
func (ve ValidationErrors) Translate(ut ut.Translator) ValidationErrorsTranslations {
|
|
|
|
trans := make(ValidationErrorsTranslations)
|
|
|
|
var fe *fieldError
|
|
|
|
for i := 0; i < len(ve); i++ {
|
|
fe = ve[i].(*fieldError)
|
|
|
|
// // in case an Anonymous struct was used, ensure that the key
|
|
// // would be 'Username' instead of ".Username"
|
|
// if len(fe.ns) > 0 && fe.ns[:1] == "." {
|
|
// trans[fe.ns[1:]] = fe.Translate(ut)
|
|
// continue
|
|
// }
|
|
|
|
trans[fe.ns] = fe.Translate(ut)
|
|
}
|
|
|
|
return trans
|
|
}
|
|
|
|
// FieldError contains all functions to get error details
|
|
type FieldError interface {
|
|
|
|
// returns the validation tag that failed. if the
|
|
// validation was an alias, this will return the
|
|
// alias name and not the underlying tag that failed.
|
|
//
|
|
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
|
|
// will return "iscolor"
|
|
Tag() string
|
|
|
|
// returns the validation tag that failed, even if an
|
|
// alias the actual tag within the alias will be returned.
|
|
// If an 'or' validation fails the entire or will be returned.
|
|
//
|
|
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
|
|
// will return "hexcolor|rgb|rgba|hsl|hsla"
|
|
ActualTag() string
|
|
|
|
// returns the namespace for the field error, with the tag
|
|
// name taking precedence over the fields actual name.
|
|
//
|
|
// eg. JSON name "User.fname"
|
|
//
|
|
// See StructNamespace() for a version that returns actual names.
|
|
//
|
|
// NOTE: this field can be blank when validating a single primitive field
|
|
// using validate.Field(...) as there is no way to extract it's name
|
|
Namespace() string
|
|
|
|
// returns the namespace for the field error, with the fields
|
|
// actual name.
|
|
//
|
|
// eq. "User.FirstName" see Namespace for comparison
|
|
//
|
|
// NOTE: this field can be blank when validating a single primitive field
|
|
// using validate.Field(...) as there is no way to extract it's name
|
|
StructNamespace() string
|
|
|
|
// returns the fields name with the tag name taking precedence over the
|
|
// fields actual name.
|
|
//
|
|
// eq. JSON name "fname"
|
|
// see StructField for comparison
|
|
Field() string
|
|
|
|
// returns the fields actual name from the struct, when able to determine.
|
|
//
|
|
// eq. "FirstName"
|
|
// see Field for comparison
|
|
StructField() string
|
|
|
|
// returns the actual fields value in case needed for creating the error
|
|
// message
|
|
Value() interface{}
|
|
|
|
// returns the param value, in string form for comparison; this will also
|
|
// help with generating an error message
|
|
Param() string
|
|
|
|
// Kind returns the Field's reflect Kind
|
|
//
|
|
// eg. time.Time's kind is a struct
|
|
Kind() reflect.Kind
|
|
|
|
// Type returns the Field's reflect Type
|
|
//
|
|
// // eg. time.Time's type is time.Time
|
|
Type() reflect.Type
|
|
|
|
// returns the FieldError's translated error
|
|
// from the provided 'ut.Translator' and registered 'TranslationFunc'
|
|
//
|
|
// NOTE: is not registered translation can be found it returns the same
|
|
// as calling fe.Error()
|
|
Translate(ut ut.Translator) string
|
|
}
|
|
|
|
// compile time interface checks
|
|
var _ FieldError = new(fieldError)
|
|
var _ error = new(fieldError)
|
|
|
|
// fieldError contains a single field's validation error along
|
|
// with other properties that may be needed for error message creation
|
|
// it complies with the FieldError interface
|
|
type fieldError struct {
|
|
v *Validate
|
|
tag string
|
|
actualTag string
|
|
ns string
|
|
structNs string
|
|
fieldLen uint8
|
|
structfieldLen uint8
|
|
value interface{}
|
|
param string
|
|
kind reflect.Kind
|
|
typ reflect.Type
|
|
}
|
|
|
|
// Tag returns the validation tag that failed.
|
|
func (fe *fieldError) Tag() string {
|
|
return fe.tag
|
|
}
|
|
|
|
// ActualTag returns the validation tag that failed, even if an
|
|
// alias the actual tag within the alias will be returned.
|
|
func (fe *fieldError) ActualTag() string {
|
|
return fe.actualTag
|
|
}
|
|
|
|
// Namespace returns the namespace for the field error, with the tag
|
|
// name taking precedence over the fields actual name.
|
|
func (fe *fieldError) Namespace() string {
|
|
return fe.ns
|
|
}
|
|
|
|
// StructNamespace returns the namespace for the field error, with the fields
|
|
// actual name.
|
|
func (fe *fieldError) StructNamespace() string {
|
|
return fe.structNs
|
|
}
|
|
|
|
// Field returns the fields name with the tag name taking precedence over the
|
|
// fields actual name.
|
|
func (fe *fieldError) Field() string {
|
|
|
|
return fe.ns[len(fe.ns)-int(fe.fieldLen):]
|
|
// // return fe.field
|
|
// fld := fe.ns[len(fe.ns)-int(fe.fieldLen):]
|
|
|
|
// log.Println("FLD:", fld)
|
|
|
|
// if len(fld) > 0 && fld[:1] == "." {
|
|
// return fld[1:]
|
|
// }
|
|
|
|
// return fld
|
|
}
|
|
|
|
// returns the fields actual name from the struct, when able to determine.
|
|
func (fe *fieldError) StructField() string {
|
|
// return fe.structField
|
|
return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):]
|
|
}
|
|
|
|
// Value returns the actual fields value in case needed for creating the error
|
|
// message
|
|
func (fe *fieldError) Value() interface{} {
|
|
return fe.value
|
|
}
|
|
|
|
// Param returns the param value, in string form for comparison; this will
|
|
// also help with generating an error message
|
|
func (fe *fieldError) Param() string {
|
|
return fe.param
|
|
}
|
|
|
|
// Kind returns the Field's reflect Kind
|
|
func (fe *fieldError) Kind() reflect.Kind {
|
|
return fe.kind
|
|
}
|
|
|
|
// Type returns the Field's reflect Type
|
|
func (fe *fieldError) Type() reflect.Type {
|
|
return fe.typ
|
|
}
|
|
|
|
// Error returns the fieldError's error message
|
|
func (fe *fieldError) Error() string {
|
|
return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag)
|
|
}
|
|
|
|
// Translate returns the FieldError's translated error
|
|
// from the provided 'ut.Translator' and registered 'TranslationFunc'
|
|
//
|
|
// NOTE: is not registered translation can be found it returns the same
|
|
// as calling fe.Error()
|
|
func (fe *fieldError) Translate(ut ut.Translator) string {
|
|
|
|
m, ok := fe.v.transTagFunc[ut]
|
|
if !ok {
|
|
return fe.Error()
|
|
}
|
|
|
|
fn, ok := m[fe.tag]
|
|
if !ok {
|
|
return fe.Error()
|
|
}
|
|
|
|
return fn(ut, fe)
|
|
}
|