gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

errors.go (7433B)


      1 package validator
      2 
      3 import (
      4 	"bytes"
      5 	"fmt"
      6 	"reflect"
      7 	"strings"
      8 
      9 	ut "github.com/go-playground/universal-translator"
     10 )
     11 
     12 const (
     13 	fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
     14 )
     15 
     16 // ValidationErrorsTranslations is the translation return type
     17 type ValidationErrorsTranslations map[string]string
     18 
     19 // InvalidValidationError describes an invalid argument passed to
     20 // `Struct`, `StructExcept`, StructPartial` or `Field`
     21 type InvalidValidationError struct {
     22 	Type reflect.Type
     23 }
     24 
     25 // Error returns InvalidValidationError message
     26 func (e *InvalidValidationError) Error() string {
     27 
     28 	if e.Type == nil {
     29 		return "validator: (nil)"
     30 	}
     31 
     32 	return "validator: (nil " + e.Type.String() + ")"
     33 }
     34 
     35 // ValidationErrors is an array of FieldError's
     36 // for use in custom error messages post validation.
     37 type ValidationErrors []FieldError
     38 
     39 // Error is intended for use in development + debugging and not intended to be a production error message.
     40 // It allows ValidationErrors to subscribe to the Error interface.
     41 // All information to create an error message specific to your application is contained within
     42 // the FieldError found within the ValidationErrors array
     43 func (ve ValidationErrors) Error() string {
     44 
     45 	buff := bytes.NewBufferString("")
     46 
     47 	for i := 0; i < len(ve); i++ {
     48 
     49 		buff.WriteString(ve[i].Error())
     50 		buff.WriteString("\n")
     51 	}
     52 
     53 	return strings.TrimSpace(buff.String())
     54 }
     55 
     56 // Translate translates all of the ValidationErrors
     57 func (ve ValidationErrors) Translate(ut ut.Translator) ValidationErrorsTranslations {
     58 
     59 	trans := make(ValidationErrorsTranslations)
     60 
     61 	var fe *fieldError
     62 
     63 	for i := 0; i < len(ve); i++ {
     64 		fe = ve[i].(*fieldError)
     65 
     66 		// // in case an Anonymous struct was used, ensure that the key
     67 		// // would be 'Username' instead of ".Username"
     68 		// if len(fe.ns) > 0 && fe.ns[:1] == "." {
     69 		// 	trans[fe.ns[1:]] = fe.Translate(ut)
     70 		// 	continue
     71 		// }
     72 
     73 		trans[fe.ns] = fe.Translate(ut)
     74 	}
     75 
     76 	return trans
     77 }
     78 
     79 // FieldError contains all functions to get error details
     80 type FieldError interface {
     81 
     82 	// Tag returns the validation tag that failed. if the
     83 	// validation was an alias, this will return the
     84 	// alias name and not the underlying tag that failed.
     85 	//
     86 	// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
     87 	// will return "iscolor"
     88 	Tag() string
     89 
     90 	// ActualTag returns the validation tag that failed, even if an
     91 	// alias the actual tag within the alias will be returned.
     92 	// If an 'or' validation fails the entire or will be returned.
     93 	//
     94 	// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
     95 	// will return "hexcolor|rgb|rgba|hsl|hsla"
     96 	ActualTag() string
     97 
     98 	// Namespace returns the namespace for the field error, with the tag
     99 	// name taking precedence over the field's actual name.
    100 	//
    101 	// eg. JSON name "User.fname"
    102 	//
    103 	// See StructNamespace() for a version that returns actual names.
    104 	//
    105 	// NOTE: this field can be blank when validating a single primitive field
    106 	// using validate.Field(...) as there is no way to extract it's name
    107 	Namespace() string
    108 
    109 	// StructNamespace returns the namespace for the field error, with the field's
    110 	// actual name.
    111 	//
    112 	// eq. "User.FirstName" see Namespace for comparison
    113 	//
    114 	// NOTE: this field can be blank when validating a single primitive field
    115 	// using validate.Field(...) as there is no way to extract its name
    116 	StructNamespace() string
    117 
    118 	// Field returns the fields name with the tag name taking precedence over the
    119 	// field's actual name.
    120 	//
    121 	// eq. JSON name "fname"
    122 	// see StructField for comparison
    123 	Field() string
    124 
    125 	// StructField returns the field's actual name from the struct, when able to determine.
    126 	//
    127 	// eq.  "FirstName"
    128 	// see Field for comparison
    129 	StructField() string
    130 
    131 	// Value returns the actual field's value in case needed for creating the error
    132 	// message
    133 	Value() interface{}
    134 
    135 	// Param returns the param value, in string form for comparison; this will also
    136 	// help with generating an error message
    137 	Param() string
    138 
    139 	// Kind returns the Field's reflect Kind
    140 	//
    141 	// eg. time.Time's kind is a struct
    142 	Kind() reflect.Kind
    143 
    144 	// Type returns the Field's reflect Type
    145 	//
    146 	// eg. time.Time's type is time.Time
    147 	Type() reflect.Type
    148 
    149 	// Translate returns the FieldError's translated error
    150 	// from the provided 'ut.Translator' and registered 'TranslationFunc'
    151 	//
    152 	// NOTE: if no registered translator can be found it returns the same as
    153 	// calling fe.Error()
    154 	Translate(ut ut.Translator) string
    155 
    156 	// Error returns the FieldError's message
    157 	Error() string
    158 }
    159 
    160 // compile time interface checks
    161 var _ FieldError = new(fieldError)
    162 var _ error = new(fieldError)
    163 
    164 // fieldError contains a single field's validation error along
    165 // with other properties that may be needed for error message creation
    166 // it complies with the FieldError interface
    167 type fieldError struct {
    168 	v              *Validate
    169 	tag            string
    170 	actualTag      string
    171 	ns             string
    172 	structNs       string
    173 	fieldLen       uint8
    174 	structfieldLen uint8
    175 	value          interface{}
    176 	param          string
    177 	kind           reflect.Kind
    178 	typ            reflect.Type
    179 }
    180 
    181 // Tag returns the validation tag that failed.
    182 func (fe *fieldError) Tag() string {
    183 	return fe.tag
    184 }
    185 
    186 // ActualTag returns the validation tag that failed, even if an
    187 // alias the actual tag within the alias will be returned.
    188 func (fe *fieldError) ActualTag() string {
    189 	return fe.actualTag
    190 }
    191 
    192 // Namespace returns the namespace for the field error, with the tag
    193 // name taking precedence over the field's actual name.
    194 func (fe *fieldError) Namespace() string {
    195 	return fe.ns
    196 }
    197 
    198 // StructNamespace returns the namespace for the field error, with the field's
    199 // actual name.
    200 func (fe *fieldError) StructNamespace() string {
    201 	return fe.structNs
    202 }
    203 
    204 // Field returns the field's name with the tag name taking precedence over the
    205 // field's actual name.
    206 func (fe *fieldError) Field() string {
    207 
    208 	return fe.ns[len(fe.ns)-int(fe.fieldLen):]
    209 	// // return fe.field
    210 	// fld := fe.ns[len(fe.ns)-int(fe.fieldLen):]
    211 
    212 	// log.Println("FLD:", fld)
    213 
    214 	// if len(fld) > 0 && fld[:1] == "." {
    215 	// 	return fld[1:]
    216 	// }
    217 
    218 	// return fld
    219 }
    220 
    221 // StructField returns the field's actual name from the struct, when able to determine.
    222 func (fe *fieldError) StructField() string {
    223 	// return fe.structField
    224 	return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):]
    225 }
    226 
    227 // Value returns the actual field's value in case needed for creating the error
    228 // message
    229 func (fe *fieldError) Value() interface{} {
    230 	return fe.value
    231 }
    232 
    233 // Param returns the param value, in string form for comparison; this will
    234 // also help with generating an error message
    235 func (fe *fieldError) Param() string {
    236 	return fe.param
    237 }
    238 
    239 // Kind returns the Field's reflect Kind
    240 func (fe *fieldError) Kind() reflect.Kind {
    241 	return fe.kind
    242 }
    243 
    244 // Type returns the Field's reflect Type
    245 func (fe *fieldError) Type() reflect.Type {
    246 	return fe.typ
    247 }
    248 
    249 // Error returns the fieldError's error message
    250 func (fe *fieldError) Error() string {
    251 	return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag)
    252 }
    253 
    254 // Translate returns the FieldError's translated error
    255 // from the provided 'ut.Translator' and registered 'TranslationFunc'
    256 //
    257 // NOTE: if no registered translation can be found, it returns the original
    258 // untranslated error message.
    259 func (fe *fieldError) Translate(ut ut.Translator) string {
    260 
    261 	m, ok := fe.v.transTagFunc[ut]
    262 	if !ok {
    263 		return fe.Error()
    264 	}
    265 
    266 	fn, ok := m[fe.tag]
    267 	if !ok {
    268 		return fe.Error()
    269 	}
    270 
    271 	return fn(ut, fe)
    272 }