summaryrefslogtreecommitdiff
path: root/vendor/github.com/go-openapi/validate/object_validator.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-openapi/validate/object_validator.go')
-rw-r--r--vendor/github.com/go-openapi/validate/object_validator.go431
1 files changed, 0 insertions, 431 deletions
diff --git a/vendor/github.com/go-openapi/validate/object_validator.go b/vendor/github.com/go-openapi/validate/object_validator.go
deleted file mode 100644
index dff73fa98..000000000
--- a/vendor/github.com/go-openapi/validate/object_validator.go
+++ /dev/null
@@ -1,431 +0,0 @@
-// Copyright 2015 go-swagger maintainers
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package validate
-
-import (
- "fmt"
- "reflect"
- "strings"
-
- "github.com/go-openapi/errors"
- "github.com/go-openapi/spec"
- "github.com/go-openapi/strfmt"
-)
-
-type objectValidator struct {
- Path string
- In string
- MaxProperties *int64
- MinProperties *int64
- Required []string
- Properties map[string]spec.Schema
- AdditionalProperties *spec.SchemaOrBool
- PatternProperties map[string]spec.Schema
- Root interface{}
- KnownFormats strfmt.Registry
- Options *SchemaValidatorOptions
- splitPath []string
-}
-
-func newObjectValidator(path, in string,
- maxProperties, minProperties *int64, required []string, properties spec.SchemaProperties,
- additionalProperties *spec.SchemaOrBool, patternProperties spec.SchemaProperties,
- root interface{}, formats strfmt.Registry, opts *SchemaValidatorOptions) *objectValidator {
- if opts == nil {
- opts = new(SchemaValidatorOptions)
- }
-
- var v *objectValidator
- if opts.recycleValidators {
- v = pools.poolOfObjectValidators.BorrowValidator()
- } else {
- v = new(objectValidator)
- }
-
- v.Path = path
- v.In = in
- v.MaxProperties = maxProperties
- v.MinProperties = minProperties
- v.Required = required
- v.Properties = properties
- v.AdditionalProperties = additionalProperties
- v.PatternProperties = patternProperties
- v.Root = root
- v.KnownFormats = formats
- v.Options = opts
- v.splitPath = strings.Split(v.Path, ".")
-
- return v
-}
-
-func (o *objectValidator) SetPath(path string) {
- o.Path = path
- o.splitPath = strings.Split(path, ".")
-}
-
-func (o *objectValidator) Applies(source interface{}, kind reflect.Kind) bool {
- // TODO: this should also work for structs
- // there is a problem in the type validator where it will be unhappy about null values
- // so that requires more testing
- _, isSchema := source.(*spec.Schema)
- return isSchema && (kind == reflect.Map || kind == reflect.Struct)
-}
-
-func (o *objectValidator) isProperties() bool {
- p := o.splitPath
- return len(p) > 1 && p[len(p)-1] == jsonProperties && p[len(p)-2] != jsonProperties
-}
-
-func (o *objectValidator) isDefault() bool {
- p := o.splitPath
- return len(p) > 1 && p[len(p)-1] == jsonDefault && p[len(p)-2] != jsonDefault
-}
-
-func (o *objectValidator) isExample() bool {
- p := o.splitPath
- return len(p) > 1 && (p[len(p)-1] == swaggerExample || p[len(p)-1] == swaggerExamples) && p[len(p)-2] != swaggerExample
-}
-
-func (o *objectValidator) checkArrayMustHaveItems(res *Result, val map[string]interface{}) {
- // for swagger 2.0 schemas, there is an additional constraint to have array items defined explicitly.
- // with pure jsonschema draft 4, one may have arrays with undefined items (i.e. any type).
- if val == nil {
- return
- }
-
- t, typeFound := val[jsonType]
- if !typeFound {
- return
- }
-
- tpe, isString := t.(string)
- if !isString || tpe != arrayType {
- return
- }
-
- item, itemsKeyFound := val[jsonItems]
- if itemsKeyFound {
- return
- }
-
- res.AddErrors(errors.Required(jsonItems, o.Path, item))
-}
-
-func (o *objectValidator) checkItemsMustBeTypeArray(res *Result, val map[string]interface{}) {
- if val == nil {
- return
- }
-
- if o.isProperties() || o.isDefault() || o.isExample() {
- return
- }
-
- _, itemsKeyFound := val[jsonItems]
- if !itemsKeyFound {
- return
- }
-
- t, typeFound := val[jsonType]
- if !typeFound {
- // there is no type
- res.AddErrors(errors.Required(jsonType, o.Path, t))
- }
-
- if tpe, isString := t.(string); !isString || tpe != arrayType {
- res.AddErrors(errors.InvalidType(o.Path, o.In, arrayType, nil))
- }
-}
-
-func (o *objectValidator) precheck(res *Result, val map[string]interface{}) {
- if o.Options.EnableArrayMustHaveItemsCheck {
- o.checkArrayMustHaveItems(res, val)
- }
- if o.Options.EnableObjectArrayTypeCheck {
- o.checkItemsMustBeTypeArray(res, val)
- }
-}
-
-func (o *objectValidator) Validate(data interface{}) *Result {
- if o.Options.recycleValidators {
- defer func() {
- o.redeem()
- }()
- }
-
- var val map[string]interface{}
- if data != nil {
- var ok bool
- val, ok = data.(map[string]interface{})
- if !ok {
- return errorHelp.sErr(invalidObjectMsg(o.Path, o.In), o.Options.recycleResult)
- }
- }
- numKeys := int64(len(val))
-
- if o.MinProperties != nil && numKeys < *o.MinProperties {
- return errorHelp.sErr(errors.TooFewProperties(o.Path, o.In, *o.MinProperties), o.Options.recycleResult)
- }
- if o.MaxProperties != nil && numKeys > *o.MaxProperties {
- return errorHelp.sErr(errors.TooManyProperties(o.Path, o.In, *o.MaxProperties), o.Options.recycleResult)
- }
-
- var res *Result
- if o.Options.recycleResult {
- res = pools.poolOfResults.BorrowResult()
- } else {
- res = new(Result)
- }
-
- o.precheck(res, val)
-
- // check validity of field names
- if o.AdditionalProperties != nil && !o.AdditionalProperties.Allows {
- // Case: additionalProperties: false
- o.validateNoAdditionalProperties(val, res)
- } else {
- // Cases: empty additionalProperties (implying: true), or additionalProperties: true, or additionalProperties: { <<schema>> }
- o.validateAdditionalProperties(val, res)
- }
-
- o.validatePropertiesSchema(val, res)
-
- // Check patternProperties
- // TODO: it looks like we have done that twice in many cases
- for key, value := range val {
- _, regularProperty := o.Properties[key]
- matched, _, patterns := o.validatePatternProperty(key, value, res) // applies to regular properties as well
- if regularProperty || !matched {
- continue
- }
-
- for _, pName := range patterns {
- if v, ok := o.PatternProperties[pName]; ok {
- r := newSchemaValidator(&v, o.Root, o.Path+"."+key, o.KnownFormats, o.Options).Validate(value)
- res.mergeForField(data.(map[string]interface{}), key, r)
- }
- }
- }
-
- return res
-}
-
-func (o *objectValidator) validateNoAdditionalProperties(val map[string]interface{}, res *Result) {
- for k := range val {
- if k == "$schema" || k == "id" {
- // special properties "$schema" and "id" are ignored
- continue
- }
-
- _, regularProperty := o.Properties[k]
- if regularProperty {
- continue
- }
-
- matched := false
- for pk := range o.PatternProperties {
- re, err := compileRegexp(pk)
- if err != nil {
- continue
- }
- if matches := re.MatchString(k); matches {
- matched = true
- break
- }
- }
- if matched {
- continue
- }
-
- res.AddErrors(errors.PropertyNotAllowed(o.Path, o.In, k))
-
- // BUG(fredbi): This section should move to a part dedicated to spec validation as
- // it will conflict with regular schemas where a property "headers" is defined.
-
- //
- // Croaks a more explicit message on top of the standard one
- // on some recognized cases.
- //
- // NOTE: edge cases with invalid type assertion are simply ignored here.
- // NOTE: prefix your messages here by "IMPORTANT!" so there are not filtered
- // by higher level callers (the IMPORTANT! tag will be eventually
- // removed).
- if k != "headers" || val[k] == nil {
- continue
- }
-
- // $ref is forbidden in header
- headers, mapOk := val[k].(map[string]interface{})
- if !mapOk {
- continue
- }
-
- for headerKey, headerBody := range headers {
- if headerBody == nil {
- continue
- }
-
- headerSchema, mapOfMapOk := headerBody.(map[string]interface{})
- if !mapOfMapOk {
- continue
- }
-
- _, found := headerSchema["$ref"]
- if !found {
- continue
- }
-
- refString, stringOk := headerSchema["$ref"].(string)
- if !stringOk {
- continue
- }
-
- msg := strings.Join([]string{", one may not use $ref=\":", refString, "\""}, "")
- res.AddErrors(refNotAllowedInHeaderMsg(o.Path, headerKey, msg))
- /*
- case "$ref":
- if val[k] != nil {
- // TODO: check context of that ref: warn about siblings, check against invalid context
- }
- */
- }
- }
-}
-
-func (o *objectValidator) validateAdditionalProperties(val map[string]interface{}, res *Result) {
- for key, value := range val {
- _, regularProperty := o.Properties[key]
- if regularProperty {
- continue
- }
-
- // Validates property against "patternProperties" if applicable
- // BUG(fredbi): succeededOnce is always false
-
- // NOTE: how about regular properties which do not match patternProperties?
- matched, succeededOnce, _ := o.validatePatternProperty(key, value, res)
- if matched || succeededOnce {
- continue
- }
-
- if o.AdditionalProperties == nil || o.AdditionalProperties.Schema == nil {
- continue
- }
-
- // Cases: properties which are not regular properties and have not been matched by the PatternProperties validator
- // AdditionalProperties as Schema
- r := newSchemaValidator(o.AdditionalProperties.Schema, o.Root, o.Path+"."+key, o.KnownFormats, o.Options).Validate(value)
- res.mergeForField(val, key, r)
- }
- // Valid cases: additionalProperties: true or undefined
-}
-
-func (o *objectValidator) validatePropertiesSchema(val map[string]interface{}, res *Result) {
- createdFromDefaults := map[string]struct{}{}
-
- // Property types:
- // - regular Property
- pSchema := pools.poolOfSchemas.BorrowSchema() // recycle a spec.Schema object which lifespan extends only to the validation of properties
- defer func() {
- pools.poolOfSchemas.RedeemSchema(pSchema)
- }()
-
- for pName := range o.Properties {
- *pSchema = o.Properties[pName]
- var rName string
- if o.Path == "" {
- rName = pName
- } else {
- rName = o.Path + "." + pName
- }
-
- // Recursively validates each property against its schema
- v, ok := val[pName]
- if ok {
- r := newSchemaValidator(pSchema, o.Root, rName, o.KnownFormats, o.Options).Validate(v)
- res.mergeForField(val, pName, r)
-
- continue
- }
-
- if pSchema.Default != nil {
- // if a default value is defined, creates the property from defaults
- // NOTE: JSON schema does not enforce default values to be valid against schema. Swagger does.
- createdFromDefaults[pName] = struct{}{}
- if !o.Options.skipSchemataResult {
- res.addPropertySchemata(val, pName, pSchema) // this shallow-clones the content of the pSchema pointer
- }
- }
- }
-
- if len(o.Required) == 0 {
- return
- }
-
- // Check required properties
- for _, k := range o.Required {
- v, ok := val[k]
- if ok {
- continue
- }
- _, isCreatedFromDefaults := createdFromDefaults[k]
- if isCreatedFromDefaults {
- continue
- }
-
- res.AddErrors(errors.Required(fmt.Sprintf("%s.%s", o.Path, k), o.In, v))
- }
-}
-
-// TODO: succeededOnce is not used anywhere
-func (o *objectValidator) validatePatternProperty(key string, value interface{}, result *Result) (bool, bool, []string) {
- if len(o.PatternProperties) == 0 {
- return false, false, nil
- }
-
- matched := false
- succeededOnce := false
- patterns := make([]string, 0, len(o.PatternProperties))
-
- schema := pools.poolOfSchemas.BorrowSchema()
- defer func() {
- pools.poolOfSchemas.RedeemSchema(schema)
- }()
-
- for k := range o.PatternProperties {
- re, err := compileRegexp(k)
- if err != nil {
- continue
- }
-
- match := re.MatchString(key)
- if !match {
- continue
- }
-
- *schema = o.PatternProperties[k]
- patterns = append(patterns, k)
- matched = true
- validator := newSchemaValidator(schema, o.Root, fmt.Sprintf("%s.%s", o.Path, key), o.KnownFormats, o.Options)
-
- res := validator.Validate(value)
- result.Merge(res)
- }
-
- return matched, succeededOnce, patterns
-}
-
-func (o *objectValidator) redeem() {
- pools.poolOfObjectValidators.RedeemValidator(o)
-}