946f02d0fc
Use of validator pkg replacing modelHelper. ValidateForm adds translated errors in messages context. To know if we have errors, we have to call messages.HasErrors() after the validation check. New translation strings for some field check. I didn't add every tag as an error since it seems we won't use them (isbn, ...). This would overload the translation files that are already big.
137 lignes
5,2 Kio
Go
137 lignes
5,2 Kio
Go
package validator
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"time"
|
|
"unicode"
|
|
|
|
"github.com/NyaaPantsu/nyaa/util/log"
|
|
msg "github.com/NyaaPantsu/nyaa/util/messages"
|
|
"github.com/go-playground/validator"
|
|
)
|
|
|
|
var validate *validator.Validate
|
|
|
|
func init() {
|
|
validate = validator.New()
|
|
validate.RegisterValidation("isutf", IsUTFLetterNumericValidator)
|
|
}
|
|
|
|
// ValidateForm : Check if a form is valid according to its tags
|
|
func ValidateForm(form interface{}, mes *msg.Messages) {
|
|
err := validate.Struct(form)
|
|
if err != nil {
|
|
for _, fieldError := range err.(validator.ValidationErrors) {
|
|
switch fieldError.Tag() {
|
|
case "required":
|
|
mes.AddErrorTf(fieldError.Field(), "error_field_needed", fieldError.Field(), fieldError.Param())
|
|
case "eq":
|
|
mes.AddErrorTf(fieldError.Field(), "error_equal", fieldError.Field(), fieldError.Param())
|
|
case "ne", "nefield", "necsfield":
|
|
mes.AddErrorTf(fieldError.Field(), "error_not_equal", fieldError.Field(), fieldError.Param())
|
|
case "eqfield", "eqcsfield":
|
|
mes.AddErrorTf(fieldError.Field(), "error_same_value", fieldError.Field(), fieldError.Param())
|
|
case "gtfield", "gtcsfield":
|
|
mes.AddErrorTf(fieldError.Field(), "error_greater_number", fieldError.Field(), fieldError.Param())
|
|
case "ltfield", "ltcsfield":
|
|
mes.AddErrorTf(fieldError.Field(), "error_less_number", fieldError.Field(), fieldError.Param())
|
|
case "gtefield", "gtecsfield":
|
|
mes.AddErrorTf(fieldError.Field(), "error_min_field", fieldError.Field(), fieldError.Param())
|
|
case "ltefield", "ltecsfield":
|
|
mes.AddErrorTf(fieldError.Field(), "error_max_field", fieldError.Field(), fieldError.Param())
|
|
case "alpha":
|
|
mes.AddErrorTf(fieldError.Field(), "error_alpha", fieldError.Field())
|
|
case "alphanum":
|
|
mes.AddErrorTf(fieldError.Field(), "error_alphanum", fieldError.Field())
|
|
case "numeric":
|
|
mes.AddErrorTf(fieldError.Field(), "error_numeric_valid", fieldError.Field())
|
|
case "number":
|
|
mes.AddErrorTf(fieldError.Field(), "error_number_valid", fieldError.Field())
|
|
case "hexadecimal":
|
|
mes.AddErrorTf(fieldError.Field(), "error_hexadecimal_valid", fieldError.Field())
|
|
case "hexcolor":
|
|
mes.AddErrorTf(fieldError.Field(), "error_hex_valid", fieldError.Field())
|
|
case "rgb":
|
|
mes.AddErrorTf(fieldError.Field(), "error_rgb_valid", fieldError.Field())
|
|
case "rgba":
|
|
mes.AddErrorTf(fieldError.Field(), "error_rgba_valid", fieldError.Field())
|
|
case "hsl":
|
|
mes.AddErrorTf(fieldError.Field(), "error_hsl_valid", fieldError.Field())
|
|
case "hsla":
|
|
mes.AddErrorTf(fieldError.Field(), "error_hsla_valid", fieldError.Field())
|
|
case "url":
|
|
mes.AddErrorTf(fieldError.Field(), "error_url_valid", fieldError.Field())
|
|
case "uri":
|
|
mes.AddErrorTf(fieldError.Field(), "error_uri_valid", fieldError.Field())
|
|
case "base64":
|
|
mes.AddErrorTf(fieldError.Field(), "error_base64_valid", fieldError.Field())
|
|
case "contains":
|
|
mes.AddErrorTf(fieldError.Field(), "error_contains", fieldError.Field(), fieldError.Param())
|
|
case "containsany":
|
|
mes.AddErrorTf(fieldError.Field(), "error_contains_any", fieldError.Field(), fieldError.Param())
|
|
case "excludes":
|
|
mes.AddErrorTf(fieldError.Field(), "error_excludes", fieldError.Field(), fieldError.Param())
|
|
case "excludesall":
|
|
mes.AddErrorTf(fieldError.Field(), "error_excludes_all", fieldError.Field(), fieldError.Param())
|
|
case "excludesrune":
|
|
mes.AddErrorTf(fieldError.Field(), "error_excludes_rune", fieldError.Field(), fieldError.Param())
|
|
case "iscolor":
|
|
mes.AddErrorTf(fieldError.Field(), "error_color_valid", fieldError.Field())
|
|
default:
|
|
switch fieldError.Kind() {
|
|
case reflect.String:
|
|
stringErrors(fieldError, mes)
|
|
case reflect.Slice, reflect.Map, reflect.Array:
|
|
case reflect.Struct:
|
|
if fieldError.Type() != reflect.TypeOf(time.Time{}) {
|
|
fmt.Printf("tag '%s' cannot be used on a struct type.", fieldError.Tag())
|
|
mes.AddErrorTf(fieldError.Field(), "error_field", fieldError.Field())
|
|
}
|
|
dateErrors(fieldError, mes)
|
|
default:
|
|
numberErrors(fieldError, mes)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bind a validated form to a model, tag omit to not bind a field
|
|
func Bind(model interface{}, form interface{}) {
|
|
modelIndirect := reflect.Indirect(reflect.ValueOf(model))
|
|
formElem := reflect.ValueOf(form).Elem()
|
|
typeOfTForm := formElem.Type()
|
|
for i := 0; i < formElem.NumField(); i++ {
|
|
tag := typeOfTForm.Field(i).Tag
|
|
if tag.Get("omit") != "true" {
|
|
modelField := modelIndirect.FieldByName(typeOfTForm.Field(i).Name)
|
|
if modelField.IsValid() {
|
|
formField := formElem.Field(i)
|
|
modelField.Set(formField)
|
|
} else {
|
|
log.Warnf("modelField : %s - %s", typeOfTForm.Field(i).Name, modelField)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// IsUTFLetterNumeric check if the string contains only unicode letters and numbers. Empty string is valid.
|
|
func IsUTFLetterNumeric(str string) bool {
|
|
if len(str) == 0 {
|
|
return true
|
|
}
|
|
for _, c := range str {
|
|
if !unicode.IsLetter(c) && !unicode.IsNumber(c) { //letters && numbers are ok
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
|
|
}
|
|
|
|
// IsUTFLetterNumericValidator is an interface to IsUTFLetterNumeric from validator
|
|
func IsUTFLetterNumericValidator(fl validator.FieldLevel) bool {
|
|
value := fl.Field().String() // value
|
|
return IsUTFLetterNumeric(value)
|
|
}
|