From c622e7c2399e4c68f478cbbdbe0f91bf3b2765ef Mon Sep 17 00:00:00 2001 From: agungdwiprasetyo Date: Mon, 10 Apr 2023 10:42:16 +0700 Subject: [PATCH] validator: change option param to interface --- Makefile | 4 +- init.go | 2 +- mocks/validator/JSONSchemaValidator.go | 39 ++++++ .../JSONSchemaValidatorOptionFunc.go | 33 ----- mocks/validator/StructValidator.go | 39 ++++++ mocks/validator/StructValidatorOptionFunc.go | 33 ----- validator/json_schema.go | 21 ++-- validator/struct.go | 113 +++++++++--------- validator/validator.go | 8 +- 9 files changed, 153 insertions(+), 139 deletions(-) create mode 100644 mocks/validator/JSONSchemaValidator.go delete mode 100644 mocks/validator/JSONSchemaValidatorOptionFunc.go create mode 100644 mocks/validator/StructValidator.go delete mode 100644 mocks/validator/StructValidatorOptionFunc.go diff --git a/Makefile b/Makefile index 7cec0441..7cb6747a 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ # mocks all interfaces mocks: - @rm -rf mocks/cmd; @mockery --all --keeptree @if [ -f mocks/candiutils/HTTPRequestOption.go ]; then rm mocks/candiutils/HTTPRequestOption.go; fi; @if [ -f mocks/candiutils/httpClientDo.go ]; then rm mocks/candiutils/httpClientDo.go; fi; @@ -17,6 +16,9 @@ mocks: @if [ -f mocks/codebase/app/rest_server/OptionFunc.go ]; then rm mocks/codebase/app/rest_server/OptionFunc.go; fi; @if [ -f mocks/codebase/app/task_queue_worker/OptionFunc.go ]; then rm mocks/codebase/app/task_queue_worker/OptionFunc.go; fi; @if [ -f mocks/codebase/factory/dependency/Option.go ]; then rm mocks/codebase/factory/dependency/Option.go; fi; + @if [ -f mocks/validator/JSONSchemaValidatorOptionFunc.go ]; then rm mocks/validator/JSONSchemaValidatorOptionFunc.go; fi; + @if [ -f mocks/validator/StructValidatorOptionFunc.go ]; then rm mocks/validator/StructValidatorOptionFunc.go; fi; + @rm -rf mocks/cmd; # unit test & calculate code coverage test: diff --git a/init.go b/init.go index 161517f3..7645cd23 100644 --- a/init.go +++ b/init.go @@ -2,5 +2,5 @@ package candi const ( // Version of this library - Version = "v1.14.3" + Version = "v1.14.4" ) diff --git a/mocks/validator/JSONSchemaValidator.go b/mocks/validator/JSONSchemaValidator.go new file mode 100644 index 00000000..b48e3502 --- /dev/null +++ b/mocks/validator/JSONSchemaValidator.go @@ -0,0 +1,39 @@ +// Code generated by mockery v2.13.1. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// JSONSchemaValidator is an autogenerated mock type for the JSONSchemaValidator type +type JSONSchemaValidator struct { + mock.Mock +} + +// ValidateDocument provides a mock function with given fields: schemaID, documentSource +func (_m *JSONSchemaValidator) ValidateDocument(schemaID string, documentSource interface{}) error { + ret := _m.Called(schemaID, documentSource) + + var r0 error + if rf, ok := ret.Get(0).(func(string, interface{}) error); ok { + r0 = rf(schemaID, documentSource) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewJSONSchemaValidator interface { + mock.TestingT + Cleanup(func()) +} + +// NewJSONSchemaValidator creates a new instance of JSONSchemaValidator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewJSONSchemaValidator(t mockConstructorTestingTNewJSONSchemaValidator) *JSONSchemaValidator { + mock := &JSONSchemaValidator{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/validator/JSONSchemaValidatorOptionFunc.go b/mocks/validator/JSONSchemaValidatorOptionFunc.go deleted file mode 100644 index 491c1463..00000000 --- a/mocks/validator/JSONSchemaValidatorOptionFunc.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by mockery v2.13.1. DO NOT EDIT. - -package mocks - -import ( - validator "github.com/golangid/candi/validator" - mock "github.com/stretchr/testify/mock" -) - -// JSONSchemaValidatorOptionFunc is an autogenerated mock type for the JSONSchemaValidatorOptionFunc type -type JSONSchemaValidatorOptionFunc struct { - mock.Mock -} - -// Execute provides a mock function with given fields: _a0 -func (_m *JSONSchemaValidatorOptionFunc) Execute(_a0 *validator.JSONSchemaValidator) { - _m.Called(_a0) -} - -type mockConstructorTestingTNewJSONSchemaValidatorOptionFunc interface { - mock.TestingT - Cleanup(func()) -} - -// NewJSONSchemaValidatorOptionFunc creates a new instance of JSONSchemaValidatorOptionFunc. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewJSONSchemaValidatorOptionFunc(t mockConstructorTestingTNewJSONSchemaValidatorOptionFunc) *JSONSchemaValidatorOptionFunc { - mock := &JSONSchemaValidatorOptionFunc{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/mocks/validator/StructValidator.go b/mocks/validator/StructValidator.go new file mode 100644 index 00000000..9f1aa6dc --- /dev/null +++ b/mocks/validator/StructValidator.go @@ -0,0 +1,39 @@ +// Code generated by mockery v2.13.1. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// StructValidator is an autogenerated mock type for the StructValidator type +type StructValidator struct { + mock.Mock +} + +// ValidateStruct provides a mock function with given fields: data +func (_m *StructValidator) ValidateStruct(data interface{}) error { + ret := _m.Called(data) + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(data) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewStructValidator interface { + mock.TestingT + Cleanup(func()) +} + +// NewStructValidator creates a new instance of StructValidator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewStructValidator(t mockConstructorTestingTNewStructValidator) *StructValidator { + mock := &StructValidator{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/validator/StructValidatorOptionFunc.go b/mocks/validator/StructValidatorOptionFunc.go deleted file mode 100644 index e28eb971..00000000 --- a/mocks/validator/StructValidatorOptionFunc.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by mockery v2.13.1. DO NOT EDIT. - -package mocks - -import ( - validator "github.com/golangid/candi/validator" - mock "github.com/stretchr/testify/mock" -) - -// StructValidatorOptionFunc is an autogenerated mock type for the StructValidatorOptionFunc type -type StructValidatorOptionFunc struct { - mock.Mock -} - -// Execute provides a mock function with given fields: _a0 -func (_m *StructValidatorOptionFunc) Execute(_a0 *validator.StructValidator) { - _m.Called(_a0) -} - -type mockConstructorTestingTNewStructValidatorOptionFunc interface { - mock.TestingT - Cleanup(func()) -} - -// NewStructValidatorOptionFunc creates a new instance of StructValidatorOptionFunc. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewStructValidatorOptionFunc(t mockConstructorTestingTNewStructValidatorOptionFunc) *StructValidatorOptionFunc { - mock := &StructValidatorOptionFunc{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/validator/json_schema.go b/validator/json_schema.go index 9af83b93..31e13102 100644 --- a/validator/json_schema.go +++ b/validator/json_schema.go @@ -10,34 +10,39 @@ import ( "github.com/golangid/gojsonschema" ) +// JSONSchemaValidator abstraction +type JSONSchemaValidator interface { + ValidateDocument(schemaID string, documentSource interface{}) error +} + // JSONSchemaValidatorOptionFunc type -type JSONSchemaValidatorOptionFunc func(*JSONSchemaValidator) +type JSONSchemaValidatorOptionFunc func(*jsonSchemaValidator) // SetSchemaStorageJSONSchemaValidatorOption option func func SetSchemaStorageJSONSchemaValidatorOption(s Storage) JSONSchemaValidatorOptionFunc { - return func(v *JSONSchemaValidator) { + return func(v *jsonSchemaValidator) { v.schemaStorage = s } } // AddHideErrorListTypeJSONSchemaValidatorOption option func func AddHideErrorListTypeJSONSchemaValidatorOption(descType ...string) JSONSchemaValidatorOptionFunc { - return func(v *JSONSchemaValidator) { + return func(v *jsonSchemaValidator) { for _, e := range descType { v.notShowErrorListType[e] = struct{}{} } } } -// JSONSchemaValidator validator -type JSONSchemaValidator struct { +// jsonSchemaValidator validator +type jsonSchemaValidator struct { schemaStorage Storage notShowErrorListType map[string]struct{} } // NewJSONSchemaValidator constructor -func NewJSONSchemaValidator(opts ...JSONSchemaValidatorOptionFunc) *JSONSchemaValidator { - v := &JSONSchemaValidator{ +func NewJSONSchemaValidator(opts ...JSONSchemaValidatorOptionFunc) JSONSchemaValidator { + v := &jsonSchemaValidator{ schemaStorage: NewInMemStorage(os.Getenv(candihelper.WORKDIR) + "api/jsonschema"), notShowErrorListType: map[string]struct{}{ "condition_else": {}, "condition_then": {}, @@ -52,7 +57,7 @@ func NewJSONSchemaValidator(opts ...JSONSchemaValidatorOptionFunc) *JSONSchemaVa } // ValidateDocument based on schema id -func (v *JSONSchemaValidator) ValidateDocument(schemaID string, documentSource interface{}) error { +func (v *jsonSchemaValidator) ValidateDocument(schemaID string, documentSource interface{}) error { s, err := v.schemaStorage.Get(schemaID) if err != nil { diff --git a/validator/struct.go b/validator/struct.go index dc205fec..92df8b2a 100644 --- a/validator/struct.go +++ b/validator/struct.go @@ -1,6 +1,7 @@ package validator import ( + "errors" "fmt" "log" "regexp" @@ -13,6 +14,11 @@ import ( "github.com/golangid/candi/candihelper" ) +// StructValidator abstraction +type StructValidator interface { + ValidateStruct(data interface{}) error +} + const ( validateValue = "{0}" @@ -46,11 +52,11 @@ var regexList = map[string]string{ } // StructValidatorOptionFunc type -type StructValidatorOptionFunc func(*StructValidator) +type StructValidatorOptionFunc func(*structValidator) // SetTranslatorStructValidatorOption option func func SetTranslatorStructValidatorOption(translator ut.Translator) StructValidatorOptionFunc { - return func(v *StructValidator) { + return func(v *structValidator) { v.translator = translator } } @@ -58,26 +64,17 @@ func SetTranslatorStructValidatorOption(translator ut.Translator) StructValidato // SetCoreStructValidatorOption option func func SetCoreStructValidatorOption(additionalConfigFunc ...func(*validatorEngine.Validate)) StructValidatorOptionFunc { - ve := validatorEngine.New() - for _, additionalFunc := range additionalConfigFunc { - additionalFunc(ve) - } - return func(v *StructValidator) { + return func(v *structValidator) { + ve := validatorEngine.New() + for _, additionalFunc := range additionalConfigFunc { + additionalFunc(ve) + } v.validator = ve } } -// StructValidator struct -type StructValidator struct { - translator ut.Translator - validator *validatorEngine.Validate -} - -// NewStructValidator using go library -// https://github.com/go-playground/validator (all struct tags will be here) -// https://godoc.org/github.com/go-playground/validator (documentation using it) -// NewStructValidator function -func NewStructValidator(opts ...StructValidatorOptionFunc) *StructValidator { +// getDefaultStructTranslatorConfig config func +func getDefaultStructTranslatorConfig(vv *validatorEngine.Validate) ut.Translator { // set default option // set lang id locales @@ -87,8 +84,6 @@ func NewStructValidator(opts ...StructValidatorOptionFunc) *StructValidator { // set translator translator, _ := uni.GetTranslator("id") - // set validator - vv := validatorEngine.New() vv.RegisterValidation(customTagRegexp, checkRegex, false) if err := vv.RegisterTranslation(customTagRegexp, translator, func(ut ut.Translator) error { @@ -102,25 +97,45 @@ func NewStructValidator(opts ...StructValidatorOptionFunc) *StructValidator { log.Println(candihelper.StringYellow(fmt.Sprintf("Struct Validator: warning, failed set translation validator on tag [%s]", customTagRegexp))) } - // register id translations idTranslations.RegisterDefaultTranslations(vv, translator) + return translator +} - // set struct validator - sv := &StructValidator{ - translator: translator, - validator: vv, - } +// checkRegex function +func checkRegex(fl validatorEngine.FieldLevel) bool { + return !regexp.MustCompile(fmt.Sprintf(`^[%s]+$+`, fl.Param())).MatchString(fl.Field().String()) +} + +// structValidator struct +type structValidator struct { + translator ut.Translator + validator *validatorEngine.Validate +} + +// NewStructValidator using go library +// https://github.com/go-playground/validator (all struct tags will be here) +// https://godoc.org/github.com/go-playground/validator (documentation using it) +// NewStructValidator function +func NewStructValidator(opts ...StructValidatorOptionFunc) StructValidator { - // overide with custom option + // set struct validator + sv := &structValidator{} for _, opt := range opts { opt(sv) } + if sv.validator == nil { + sv.validator = validatorEngine.New() + } + if sv.translator == nil { + sv.translator = getDefaultStructTranslatorConfig(sv.validator) + } + return sv } // regexError function -func (v *StructValidator) regexError(errString string) string { +func (v *structValidator) regexError(errString string) string { var ( result string replacer []string @@ -136,46 +151,26 @@ func (v *StructValidator) regexError(errString string) string { return result } -// CUSTOM FUNCTION SECTION -// checkRegex function -func checkRegex(fl validatorEngine.FieldLevel) bool { - var ( - param = fl.Param() - value = fl.Field().String() - result = true - ) - - // regexp - regex := regexp.MustCompile(fmt.Sprintf(`^[%s]+$+`, param)) - - if !regex.MatchString(value) { - result = false - } - - return result -} - // ValidateStruct function -func (v *StructValidator) ValidateStruct(data interface{}) error { - multiError := candihelper.NewMultiError() +func (v *structValidator) ValidateStruct(data interface{}) error { err := v.validator.Struct(data) if err != nil { switch errs := err.(type) { case validatorEngine.ValidationErrors: + multiError := candihelper.NewMultiError() for _, e := range errs { - message := e.Translate(v.translator) - - if e.Tag() == customTagRegexp { - message = fmt.Sprintf("%s%s", message, v.regexError(e.Param())) + message := err.Error() + if v.translator != nil { + message = e.Translate(v.translator) } - - // can translate each error one at a time. - multiError.Append(strings.ToLower(e.Field()), fmt.Errorf(message)) - - if multiError.HasError() { - return multiError + if e.Tag() == customTagRegexp { + message = message + v.regexError(e.Param()) } + multiError.Append(strings.ToLower(e.Field()), errors.New(message)) + } + if multiError.HasError() { + return multiError } default: return err diff --git a/validator/validator.go b/validator/validator.go index c13c07cb..68748e22 100644 --- a/validator/validator.go +++ b/validator/validator.go @@ -4,14 +4,14 @@ package validator type OptionFunc func(*Validator) // SetJSONSchemaValidator option func -func SetJSONSchemaValidator(jsonSchema *JSONSchemaValidator) OptionFunc { +func SetJSONSchemaValidator(jsonSchema JSONSchemaValidator) OptionFunc { return func(v *Validator) { v.jsonSchema = jsonSchema } } // SetStructValidator option func -func SetStructValidator(structValidator *StructValidator) OptionFunc { +func SetStructValidator(structValidator StructValidator) OptionFunc { return func(v *Validator) { v.structValidator = structValidator } @@ -19,8 +19,8 @@ func SetStructValidator(structValidator *StructValidator) OptionFunc { // Validator instance type Validator struct { - jsonSchema *JSONSchemaValidator - structValidator *StructValidator + jsonSchema JSONSchemaValidator + structValidator StructValidator } // NewValidator constructor, using jsonschema & struct validator (github.com/go-playground/validator),