This commit is contained in:
2024-07-19 17:04:42 +02:00
commit 5e0d0ec69f
71 changed files with 3316 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
package validator
import (
"errors"
"fmt"
"mangezmieux-backend/internal/logger"
"mangezmieux-backend/internal/responses"
"regexp"
"strings"
validatorLib "github.com/go-playground/validator/v10"
)
var regexpValidatorNamespacePrefix = regexp.MustCompile(`^\w+\.`)
func NewDataValidationAPIError(err error) responses.APIError {
apiErr := responses.ErrDataValidation
if err != nil {
var invalidValidationErrror *validatorLib.InvalidValidationError
if errors.As(err, &invalidValidationErrror) {
logger.GetLogger().WithError(invalidValidationErrror).WithField("templateAPIErr", apiErr).Error("InvalidValidationError")
} else {
var validationErrors validatorLib.ValidationErrors
if errors.As(err, &validationErrors) {
for _, e := range validationErrors {
reason := e.Tag()
if _, ok := CustomValidators[e.Tag()]; ok {
reason = truncatingSprintf(CustomValidators[e.Tag()].Message, e.Param())
}
namespaceWithoutStructName := regexpValidatorNamespacePrefix.ReplaceAllString(e.Namespace(), "")
fe := responses.FieldError{
Field: namespaceWithoutStructName,
Constraint: e.Tag(),
Description: reason,
}
apiErr.Details = append(apiErr.Details, fe)
}
} else {
apiErr.Description = err.Error()
}
}
}
return apiErr
}
// truncatingSprintf is used as fmt.Sprintf but allow to truncate the additional parameters given when there is more parameters than %v in str.
func truncatingSprintf(str string, args ...interface{}) string {
n := strings.Count(str, "%v")
return fmt.Sprintf(str, args[:n]...)
}

View File

@@ -0,0 +1,9 @@
package validator
import "mangezmieux-backend/internal/injector"
const ValidatorInjectorKey = "VALIDATOR"
func Setup(inj *injector.Injector) {
inj.Set(ValidatorInjectorKey, newValidator())
}

View File

@@ -0,0 +1,56 @@
package validator
import (
"context"
"reflect"
"strings"
validatorLib "github.com/go-playground/validator/v10"
)
var CustomValidators = map[string]customValidator{
"enum": {
Message: "This field should be in: %v",
Validator: validateEnum,
},
"required": {
Message: "This field is required and cannot be empty",
},
}
type customValidator struct {
Message string
Validator validatorLib.FuncCtx
}
func validateEnum(ctx context.Context, fl validatorLib.FieldLevel) bool {
for _, v := range strings.Split(fl.Param(), " ") {
if v == fl.Field().String() {
return true
}
}
return false
}
func newValidator() *validatorLib.Validate {
va := validatorLib.New()
va.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)
if len(name) < 1 {
return ""
}
return name[0]
})
for k, v := range CustomValidators {
if v.Validator != nil {
err := va.RegisterValidationCtx(k, v.Validator)
if err != nil {
return nil
}
}
}
return va
}