policy-generator/cmd/policygen/validator.go

107 lines
2.4 KiB
Go

package main
import (
"fmt"
"github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
)
type Validator struct {
validate *validator.Validate
trans ut.Translator
}
func (v Validator) Struct(i interface{}) error {
err := v.validate.Struct(i)
return v.Translate(err)
}
type Translation struct {
format string
params func(fe validator.FieldError) []any
}
var translations = map[string]Translation{
"oneof": {
"{0} must be one of [{1}], got '{2}'",
func(fe validator.FieldError) []any {
return []any{fe.Namespace(), fe.Param(), fe.Value()}
},
},
}
type TranslatedFieldError struct {
validator.FieldError
msg string
}
func NewTranslatedFieldError(msg string, e validator.FieldError) TranslatedFieldError {
return TranslatedFieldError{
FieldError: e,
msg: msg,
}
}
func (e TranslatedFieldError) Error() string {
return e.msg
}
func NewValidator() (*Validator, error) {
validate := validator.New(validator.WithRequiredStructEnabled())
language := en.New()
translator := ut.New(language, language)
trans, ok := translator.GetTranslator("en")
if !ok {
return nil, fmt.Errorf("Could not find translator to print error meesage")
}
en_translations.RegisterDefaultTranslations(validate, trans)
for validation, translation := range translations {
validate.RegisterTranslation(validation, trans,
func(ut ut.Translator) error {
return ut.Add(validation, translation.format, true)
},
func(ut ut.Translator, fe validator.FieldError) string {
params := translation.params(fe)
stringParams := make([]string, len(params))
for i, param := range params {
stringParams[i] = fmt.Sprintf("%s", param)
}
t, _ := ut.T(validation, stringParams...)
return t
})
}
return &Validator{
validate: validate,
trans: trans,
}, nil
}
func (v Validator) ValidateStruct(s interface{}) error {
err := v.validate.Struct(s)
return v.Translate(err)
}
func (v Validator) Translate(err error) error {
if err == nil {
return err
}
errs, ok := err.(validator.ValidationErrors)
if !ok {
return err
}
var errorList validator.ValidationErrors = nil
for _, e := range errs {
var translation validator.FieldError = TranslatedFieldError{
FieldError: e,
msg: e.Translate(v.trans),
}
errorList = append(errorList, translation)
}
return errorList
}