podman

Форк
0
260 строк · 7.2 Кб
1
// Copyright 2015 go-swagger maintainers
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package validate
16

17
import (
18
	"encoding/json"
19
	"reflect"
20

21
	"github.com/go-openapi/errors"
22
	"github.com/go-openapi/spec"
23
	"github.com/go-openapi/strfmt"
24
	"github.com/go-openapi/swag"
25
)
26

27
var (
28
	specSchemaType    = reflect.TypeOf(&spec.Schema{})
29
	specParameterType = reflect.TypeOf(&spec.Parameter{})
30
	specHeaderType    = reflect.TypeOf(&spec.Header{})
31
	// specItemsType     = reflect.TypeOf(&spec.Items{})
32
)
33

34
// SchemaValidator validates data against a JSON schema
35
type SchemaValidator struct {
36
	Path         string
37
	in           string
38
	Schema       *spec.Schema
39
	validators   []valueValidator
40
	Root         interface{}
41
	KnownFormats strfmt.Registry
42
	Options      SchemaValidatorOptions
43
}
44

45
// AgainstSchema validates the specified data against the provided schema, using a registry of supported formats.
46
//
47
// When no pre-parsed *spec.Schema structure is provided, it uses a JSON schema as default. See example.
48
func AgainstSchema(schema *spec.Schema, data interface{}, formats strfmt.Registry, options ...Option) error {
49
	res := NewSchemaValidator(schema, nil, "", formats, options...).Validate(data)
50
	if res.HasErrors() {
51
		return errors.CompositeValidationError(res.Errors...)
52
	}
53
	return nil
54
}
55

56
// NewSchemaValidator creates a new schema validator.
57
//
58
// Panics if the provided schema is invalid.
59
func NewSchemaValidator(schema *spec.Schema, rootSchema interface{}, root string, formats strfmt.Registry, options ...Option) *SchemaValidator {
60
	if schema == nil {
61
		return nil
62
	}
63

64
	if rootSchema == nil {
65
		rootSchema = schema
66
	}
67

68
	if schema.ID != "" || schema.Ref.String() != "" || schema.Ref.IsRoot() {
69
		err := spec.ExpandSchema(schema, rootSchema, nil)
70
		if err != nil {
71
			msg := invalidSchemaProvidedMsg(err).Error()
72
			panic(msg)
73
		}
74
	}
75
	s := SchemaValidator{
76
		Path:         root,
77
		in:           "body",
78
		Schema:       schema,
79
		Root:         rootSchema,
80
		KnownFormats: formats,
81
		Options:      SchemaValidatorOptions{}}
82
	for _, o := range options {
83
		o(&s.Options)
84
	}
85
	s.validators = []valueValidator{
86
		s.typeValidator(),
87
		s.schemaPropsValidator(),
88
		s.stringValidator(),
89
		s.formatValidator(),
90
		s.numberValidator(),
91
		s.sliceValidator(),
92
		s.commonValidator(),
93
		s.objectValidator(),
94
	}
95
	return &s
96
}
97

98
// SetPath sets the path for this schema valdiator
99
func (s *SchemaValidator) SetPath(path string) {
100
	s.Path = path
101
}
102

103
// Applies returns true when this schema validator applies
104
func (s *SchemaValidator) Applies(source interface{}, kind reflect.Kind) bool {
105
	_, ok := source.(*spec.Schema)
106
	return ok
107
}
108

109
// Validate validates the data against the schema
110
func (s *SchemaValidator) Validate(data interface{}) *Result {
111
	result := &Result{data: data}
112
	if s == nil {
113
		return result
114
	}
115
	if s.Schema != nil {
116
		result.addRootObjectSchemata(s.Schema)
117
	}
118

119
	if data == nil {
120
		result.Merge(s.validators[0].Validate(data)) // type validator
121
		result.Merge(s.validators[6].Validate(data)) // common validator
122
		return result
123
	}
124

125
	tpe := reflect.TypeOf(data)
126
	kind := tpe.Kind()
127
	for kind == reflect.Ptr {
128
		tpe = tpe.Elem()
129
		kind = tpe.Kind()
130
	}
131
	d := data
132

133
	if kind == reflect.Struct {
134
		// NOTE: since reflect retrieves the true nature of types
135
		// this means that all strfmt types passed here (e.g. strfmt.Datetime, etc..)
136
		// are converted here to strings, and structs are systematically converted
137
		// to map[string]interface{}.
138
		d = swag.ToDynamicJSON(data)
139
	}
140

141
	// TODO: this part should be handed over to type validator
142
	// Handle special case of json.Number data (number marshalled as string)
143
	isnumber := s.Schema.Type.Contains(numberType) || s.Schema.Type.Contains(integerType)
144
	if num, ok := data.(json.Number); ok && isnumber {
145
		if s.Schema.Type.Contains(integerType) { // avoid lossy conversion
146
			in, erri := num.Int64()
147
			if erri != nil {
148
				result.AddErrors(invalidTypeConversionMsg(s.Path, erri))
149
				result.Inc()
150
				return result
151
			}
152
			d = in
153
		} else {
154
			nf, errf := num.Float64()
155
			if errf != nil {
156
				result.AddErrors(invalidTypeConversionMsg(s.Path, errf))
157
				result.Inc()
158
				return result
159
			}
160
			d = nf
161
		}
162

163
		tpe = reflect.TypeOf(d)
164
		kind = tpe.Kind()
165
	}
166

167
	for _, v := range s.validators {
168
		if !v.Applies(s.Schema, kind) {
169
			debugLog("%T does not apply for %v", v, kind)
170
			continue
171
		}
172

173
		err := v.Validate(d)
174
		result.Merge(err)
175
		result.Inc()
176
	}
177
	result.Inc()
178

179
	return result
180
}
181

182
func (s *SchemaValidator) typeValidator() valueValidator {
183
	return &typeValidator{Type: s.Schema.Type, Nullable: s.Schema.Nullable, Format: s.Schema.Format, In: s.in, Path: s.Path}
184
}
185

186
func (s *SchemaValidator) commonValidator() valueValidator {
187
	return &basicCommonValidator{
188
		Path: s.Path,
189
		In:   s.in,
190
		Enum: s.Schema.Enum,
191
	}
192
}
193

194
func (s *SchemaValidator) sliceValidator() valueValidator {
195
	return &schemaSliceValidator{
196
		Path:            s.Path,
197
		In:              s.in,
198
		MaxItems:        s.Schema.MaxItems,
199
		MinItems:        s.Schema.MinItems,
200
		UniqueItems:     s.Schema.UniqueItems,
201
		AdditionalItems: s.Schema.AdditionalItems,
202
		Items:           s.Schema.Items,
203
		Root:            s.Root,
204
		KnownFormats:    s.KnownFormats,
205
		Options:         s.Options,
206
	}
207
}
208

209
func (s *SchemaValidator) numberValidator() valueValidator {
210
	return &numberValidator{
211
		Path:             s.Path,
212
		In:               s.in,
213
		Default:          s.Schema.Default,
214
		MultipleOf:       s.Schema.MultipleOf,
215
		Maximum:          s.Schema.Maximum,
216
		ExclusiveMaximum: s.Schema.ExclusiveMaximum,
217
		Minimum:          s.Schema.Minimum,
218
		ExclusiveMinimum: s.Schema.ExclusiveMinimum,
219
	}
220
}
221

222
func (s *SchemaValidator) stringValidator() valueValidator {
223
	return &stringValidator{
224
		Path:      s.Path,
225
		In:        s.in,
226
		MaxLength: s.Schema.MaxLength,
227
		MinLength: s.Schema.MinLength,
228
		Pattern:   s.Schema.Pattern,
229
	}
230
}
231

232
func (s *SchemaValidator) formatValidator() valueValidator {
233
	return &formatValidator{
234
		Path:         s.Path,
235
		In:           s.in,
236
		Format:       s.Schema.Format,
237
		KnownFormats: s.KnownFormats,
238
	}
239
}
240

241
func (s *SchemaValidator) schemaPropsValidator() valueValidator {
242
	sch := s.Schema
243
	return newSchemaPropsValidator(s.Path, s.in, sch.AllOf, sch.OneOf, sch.AnyOf, sch.Not, sch.Dependencies, s.Root, s.KnownFormats, s.Options.Options()...)
244
}
245

246
func (s *SchemaValidator) objectValidator() valueValidator {
247
	return &objectValidator{
248
		Path:                 s.Path,
249
		In:                   s.in,
250
		MaxProperties:        s.Schema.MaxProperties,
251
		MinProperties:        s.Schema.MinProperties,
252
		Required:             s.Schema.Required,
253
		Properties:           s.Schema.Properties,
254
		AdditionalProperties: s.Schema.AdditionalProperties,
255
		PatternProperties:    s.Schema.PatternProperties,
256
		Root:                 s.Root,
257
		KnownFormats:         s.KnownFormats,
258
		Options:              s.Options,
259
	}
260
}
261

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.