diff --git a/.golangci.yml b/.golangci.yml index 443058c..23fb27e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,12 +1,12 @@ run: timeout: 5m -linters-settings: - importas: - alias: - - pkg: '^github.com\/foomo\/contentfulvalidation\/(.*\/)?([^\/]+)\/?$' - alias: '${2}x' # enforce `x` suffix - no-unaliased: true +# linters-settings: +# importas: +# alias: +# - pkg: '^github.com\/foomo\/contentfulvalidation\/(.*\/)?([^\/]+)\/?$' +# alias: '${2}x' # enforce `x` suffix +# no-unaliased: true linters: enable: @@ -20,7 +20,7 @@ linters: # Disabled by default linters: - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false] - bidichk # Checks for dangerous unicode character sequences [fast: true, auto-fix: false] - - depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false] + # - depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false] - dupl # Tool for code clone detection [fast: true, auto-fix: false] - forcetypeassert # finds forced type assertions [fast: true, auto-fix: false] - gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false] @@ -32,7 +32,7 @@ linters: - goprintffuncname # Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false] - gosec # (gas): Inspects source code for security problems [fast: false, auto-fix: false] - grouper # An analyzer to analyze expression groups. [fast: true, auto-fix: false] - - importas # Enforces consistent import aliases [fast: false, auto-fix: false] + # - importas # Enforces consistent import aliases [fast: false, auto-fix: false] - maintidx # maintidx measures the maintainability index of each function. [fast: true, auto-fix: false] - makezero # Finds slice declarations with non-zero initial length [fast: false, auto-fix: false] - misspell # Finds commonly misspelled English words in comments [fast: true, auto-fix: true] diff --git a/constants/vo.go b/constants/vo.go index 7c63a42..8e861d7 100644 --- a/constants/vo.go +++ b/constants/vo.go @@ -1,5 +1,148 @@ package constants +import ( + "github.com/RoaringBitmap/roaring" +) + type Severity string type Health string type QueryError string + +type ( + AttributeID string + AttributeValueID string + AttributeType string + + // Locale like en or en_us + Locale string + LocalizedString map[Locale]string +) + +type Attributes map[AttributeID]AttributeDefinition + +// AttributeDefinition describes an attribute. +type AttributeDefinition struct { + ID AttributeID `json:"id"` + Type AttributeType `json:"type"` + EnumStrings map[AttributeValueID]*string `json:"enumStrings,omitempty"` + Meta AttributeMeta `json:"meta,omitempty"` + MetaValues map[AttributeValueID]AttributeMeta `json:"metaValues,omitempty"` + StepSize int `json:"stepSize,omitempty"` + Mandatory bool `json:"mandatory,omitempty"` +} + +// AttributeMeta models meta information for an attribute. +type AttributeMeta struct { + Label LocalizedString `json:"label,omitempty"` + Description LocalizedString `json:"description,omitempty"` + Custom map[string]string `json:"custom,omitempty"` + SortingRank map[string]int `json:"sortingRank,omitempty"` +} + +// Query structure +type Query struct { + Explanation string `json:"explanation,omitempty"` + Operation Operation `json:"operation"` + Elements []*QueryElement `json:"elements"` +} + +// Operation defines how to compare bitmaps +type Operation string + +// QueryElement structure +type QueryElement struct { + Matcher *Matcher `json:"matcher,omitempty"` + Query *Query `json:"query,omitempty"` +} + +// Matcher structure +// Identifies a bitmap +// the result of each match operation is a bitmap of entity ids +type Matcher struct { + Attribute AttributeID `json:"attribute,omitempty"` + Explanation string `json:"explanation,omitempty"` + + // strings + StringIn *StringIn `json:"stringIn,omitempty"` + StringAllIn *StringAllIn `json:"stringAllIn,omitempty"` + StringNotIn *StringNotIn `json:"stringNotIn,omitempty"` + StringEquals *StringEquals `json:"stringEquals,omitempty"` + StringNotEquals *StringNotEquals `json:"stringNotEquals,omitempty"` + + // integers + IntInRange *IntInRange `json:"intInRange,omitempty"` + IntFrom *IntFrom `json:"intFrom,omitempty"` + IntTo *IntTo `json:"intTo,omitempty"` + IntEquals *IntEquals `json:"intEquals,omitempty"` + IntNotEquals *IntNotEquals `json:"intNotEquals,omitempty"` + + // booleans + BoolEquals *BoolEquals `json:"boolEquals,omitempty"` + + // bitmap + Bitmap *Bitmap `json:"bitmap,omitempty"` +} + +// StringIn matches if the input value equals any of the strings specified +type StringIn struct { + Values []string `json:"values"` +} + +// StringAllIn matches if all values appear in the input +type StringAllIn struct { + Values []string `json:"values"` +} + +// StringNotIn matches if the input value does not equal any of the strings specified +type StringNotIn struct { + Values []string `json:"values"` +} + +// StringEquals matches strings that DO equal the supplied value +type StringEquals struct { + Value string `json:"value"` +} + +// StringNotEquals matches strings that DO NOT equal the supplied value +type StringNotEquals struct { + Value string `json:"value"` +} + +// IntInRange matches integers in the given range +type IntInRange struct { + From int `json:"from"` + To int `json:"to"` +} + +// IntFrom matches integers starting from the given value (>=) +type IntFrom struct { + From int `json:"from"` +} + +// IntTo matches integers until the given value (<=) +type IntTo struct { + To int `json:"to"` +} + +// IntEquals matches integers exactly (==) +type IntEquals struct { + Value int `json:"value"` +} + +// IntNotEquals matches integers that do not equal the given value (!=) +type IntNotEquals struct { + Value int `json:"value"` +} + +// BoolEquals matches booleans exactly (==) +type BoolEquals struct { + Value bool `json:"value"` +} + +// Bitmap allows to use a *roaring.Bitmap directly for a matcher +type Bitmap struct { + // value is private to hide it from gotsrpc + value *roaring.Bitmap `json:"-"` + + FacetValue string `json:"facetValue"` +} diff --git a/go.mod b/go.mod index 083f967..133a9bb 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/foomo/contentfulvalidation go 1.20 require ( - github.com/bestbytes/catalogue v0.39.0 + github.com/RoaringBitmap/roaring v1.3.0 github.com/foomo/contentful v0.4.4 github.com/foomo/contentserver v1.10.2 github.com/foomo/gotsrpc/v2 v2.7.2 @@ -14,7 +14,6 @@ require ( ) require ( - github.com/RoaringBitmap/roaring v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect diff --git a/go.sum b/go.sum index a4d1432..c32c3f9 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,6 @@ github.com/RoaringBitmap/roaring v1.3.0/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bestbytes/catalogue v0.39.0 h1:UYUhABB7ByGuxZNdr+9CqK4DZtmC9UIB37MpTJyDmAk= -github.com/bestbytes/catalogue v0.39.0/go.mod h1:eyZEeaZJSqc/r78jejYM+h8fkLnS1Kzd+IPzG0hxLH0= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= diff --git a/utils/utils.go b/utils/utils.go index 0139009..e60751a 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -4,8 +4,8 @@ import ( "encoding/json" "time" - catvo "github.com/bestbytes/catalogue/vo" "github.com/foomo/contentful" + "github.com/foomo/contentfulvalidation/constants" "github.com/pkg/errors" ) @@ -43,8 +43,8 @@ func GetAspectRatio(asset *contentful.AssetNoLocale) (float64, error) { return aspectRatio, nil } -func LoadQuery(rawQuery any) (*catvo.Query, error) { - query := &catvo.Query{} +func LoadQuery(rawQuery *interface{}) (*constants.Query, error) { + query := &constants.Query{} errMarshal := loadInterfaceAsJSON(rawQuery, query) if errMarshal != nil { return nil, errMarshal diff --git a/validations/query.go b/validations/query.go index 9111bd7..fe7c75a 100644 --- a/validations/query.go +++ b/validations/query.go @@ -1,24 +1,23 @@ package validations import ( - catvo "github.com/bestbytes/catalogue/vo" "github.com/foomo/contentfulvalidation/constants" ) -func ValidateQuery(query *catvo.Query, attributes catvo.Attributes) []constants.QueryError { +func ValidateQuery(query *constants.Query, attributes constants.Attributes) []constants.QueryError { errors := []constants.QueryError{} - isValueExpired := func(value string, def catvo.AttributeDefinition) { + isValueExpired := func(value string, def constants.AttributeDefinition) { if len(value) < 1 { errors = append(errors, constants.MissingQueryFieldValues) } else { - if _, ok := def.EnumStrings[catvo.AttributeValueID(value)]; !ok { + if _, ok := def.EnumStrings[constants.AttributeValueID(value)]; !ok { errors = append(errors, constants.QueryValueExpired) } } } - areValuesExpired := func(values []string, def catvo.AttributeDefinition) { + areValuesExpired := func(values []string, def constants.AttributeDefinition) { if len(values) < 1 { errors = append(errors, constants.MissingQueryFieldValues) } diff --git a/validator/attributeprovider.go b/validator/attributeprovider.go index 8defb83..ea6a121 100644 --- a/validator/attributeprovider.go +++ b/validator/attributeprovider.go @@ -4,19 +4,19 @@ import ( "context" "time" - "github.com/bestbytes/catalogue/vo" + "github.com/foomo/contentfulvalidation/constants" "github.com/foomo/keel/log" "github.com/go-co-op/gocron" "go.uber.org/zap" ) -type AttributeProviderFunc func() vo.Attributes -type AttributeUpdateFunc func(ctx context.Context) vo.Attributes +type AttributeProviderFunc func() constants.Attributes +type AttributeUpdateFunc func(ctx context.Context) constants.Attributes type AttributeProvider struct { l *zap.Logger ctx context.Context - attributes vo.Attributes + attributes constants.Attributes updateFunc AttributeUpdateFunc } @@ -43,6 +43,6 @@ func (ap *AttributeProvider) Init() error { return nil } -func (ap *AttributeProvider) GetAttributes() vo.Attributes { +func (ap *AttributeProvider) GetAttributes() constants.Attributes { return ap.attributes } diff --git a/validator/interfaces.go b/validator/interfaces.go index 24a9aa7..2249ad7 100644 --- a/validator/interfaces.go +++ b/validator/interfaces.go @@ -7,6 +7,6 @@ type ModelValidator interface { ValidateAll() (map[ModelID]*ValidationResult, error) } -type ValidatorProvider interface { +type ValidatorProvider interface { //nolint:revive GetValidators() map[ModelType]ModelValidator }