podman

Форк
0
645 строк · 17.7 Кб
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
	"fmt"
19
	"reflect"
20

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

26
// An EntityValidator is an interface for things that can validate entities
27
type EntityValidator interface {
28
	Validate(interface{}) *Result
29
}
30

31
type valueValidator interface {
32
	SetPath(path string)
33
	Applies(interface{}, reflect.Kind) bool
34
	Validate(interface{}) *Result
35
}
36

37
type itemsValidator struct {
38
	items        *spec.Items
39
	root         interface{}
40
	path         string
41
	in           string
42
	validators   []valueValidator
43
	KnownFormats strfmt.Registry
44
}
45

46
func newItemsValidator(path, in string, items *spec.Items, root interface{}, formats strfmt.Registry) *itemsValidator {
47
	iv := &itemsValidator{path: path, in: in, items: items, root: root, KnownFormats: formats}
48
	iv.validators = []valueValidator{
49
		&typeValidator{
50
			Type:     spec.StringOrArray([]string{items.Type}),
51
			Nullable: items.Nullable,
52
			Format:   items.Format,
53
			In:       in,
54
			Path:     path,
55
		},
56
		iv.stringValidator(),
57
		iv.formatValidator(),
58
		iv.numberValidator(),
59
		iv.sliceValidator(),
60
		iv.commonValidator(),
61
	}
62
	return iv
63
}
64

65
func (i *itemsValidator) Validate(index int, data interface{}) *Result {
66
	tpe := reflect.TypeOf(data)
67
	kind := tpe.Kind()
68
	mainResult := new(Result)
69
	path := fmt.Sprintf("%s.%d", i.path, index)
70

71
	for _, validator := range i.validators {
72
		validator.SetPath(path)
73
		if validator.Applies(i.root, kind) {
74
			result := validator.Validate(data)
75
			mainResult.Merge(result)
76
			mainResult.Inc()
77
			if result != nil && result.HasErrors() {
78
				return mainResult
79
			}
80
		}
81
	}
82
	return mainResult
83
}
84

85
func (i *itemsValidator) commonValidator() valueValidator {
86
	return &basicCommonValidator{
87
		In:      i.in,
88
		Default: i.items.Default,
89
		Enum:    i.items.Enum,
90
	}
91
}
92

93
func (i *itemsValidator) sliceValidator() valueValidator {
94
	return &basicSliceValidator{
95
		In:           i.in,
96
		Default:      i.items.Default,
97
		MaxItems:     i.items.MaxItems,
98
		MinItems:     i.items.MinItems,
99
		UniqueItems:  i.items.UniqueItems,
100
		Source:       i.root,
101
		Items:        i.items.Items,
102
		KnownFormats: i.KnownFormats,
103
	}
104
}
105

106
func (i *itemsValidator) numberValidator() valueValidator {
107
	return &numberValidator{
108
		In:               i.in,
109
		Default:          i.items.Default,
110
		MultipleOf:       i.items.MultipleOf,
111
		Maximum:          i.items.Maximum,
112
		ExclusiveMaximum: i.items.ExclusiveMaximum,
113
		Minimum:          i.items.Minimum,
114
		ExclusiveMinimum: i.items.ExclusiveMinimum,
115
		Type:             i.items.Type,
116
		Format:           i.items.Format,
117
	}
118
}
119

120
func (i *itemsValidator) stringValidator() valueValidator {
121
	return &stringValidator{
122
		In:              i.in,
123
		Default:         i.items.Default,
124
		MaxLength:       i.items.MaxLength,
125
		MinLength:       i.items.MinLength,
126
		Pattern:         i.items.Pattern,
127
		AllowEmptyValue: false,
128
	}
129
}
130

131
func (i *itemsValidator) formatValidator() valueValidator {
132
	return &formatValidator{
133
		In: i.in,
134
		//Default:      i.items.Default,
135
		Format:       i.items.Format,
136
		KnownFormats: i.KnownFormats,
137
	}
138
}
139

140
type basicCommonValidator struct {
141
	Path    string
142
	In      string
143
	Default interface{}
144
	Enum    []interface{}
145
}
146

147
func (b *basicCommonValidator) SetPath(path string) {
148
	b.Path = path
149
}
150

151
func (b *basicCommonValidator) Applies(source interface{}, kind reflect.Kind) bool {
152
	switch source.(type) {
153
	case *spec.Parameter, *spec.Schema, *spec.Header:
154
		return true
155
	}
156
	return false
157
}
158

159
func (b *basicCommonValidator) Validate(data interface{}) (res *Result) {
160
	if len(b.Enum) > 0 {
161
		for _, enumValue := range b.Enum {
162
			actualType := reflect.TypeOf(enumValue)
163
			if actualType != nil { // Safeguard
164
				expectedValue := reflect.ValueOf(data)
165
				if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
166
					if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
167
						return nil
168
					}
169
				}
170
			}
171
		}
172
		return errorHelp.sErr(errors.EnumFail(b.Path, b.In, data, b.Enum))
173
	}
174
	return nil
175
}
176

177
// A HeaderValidator has very limited subset of validations to apply
178
type HeaderValidator struct {
179
	name         string
180
	header       *spec.Header
181
	validators   []valueValidator
182
	KnownFormats strfmt.Registry
183
}
184

185
// NewHeaderValidator creates a new header validator object
186
func NewHeaderValidator(name string, header *spec.Header, formats strfmt.Registry) *HeaderValidator {
187
	p := &HeaderValidator{name: name, header: header, KnownFormats: formats}
188
	p.validators = []valueValidator{
189
		&typeValidator{
190
			Type:     spec.StringOrArray([]string{header.Type}),
191
			Nullable: header.Nullable,
192
			Format:   header.Format,
193
			In:       "header",
194
			Path:     name,
195
		},
196
		p.stringValidator(),
197
		p.formatValidator(),
198
		p.numberValidator(),
199
		p.sliceValidator(),
200
		p.commonValidator(),
201
	}
202
	return p
203
}
204

205
// Validate the value of the header against its schema
206
func (p *HeaderValidator) Validate(data interface{}) *Result {
207
	result := new(Result)
208
	tpe := reflect.TypeOf(data)
209
	kind := tpe.Kind()
210

211
	for _, validator := range p.validators {
212
		if validator.Applies(p.header, kind) {
213
			if err := validator.Validate(data); err != nil {
214
				result.Merge(err)
215
				if err.HasErrors() {
216
					return result
217
				}
218
			}
219
		}
220
	}
221
	return nil
222
}
223

224
func (p *HeaderValidator) commonValidator() valueValidator {
225
	return &basicCommonValidator{
226
		Path:    p.name,
227
		In:      "response",
228
		Default: p.header.Default,
229
		Enum:    p.header.Enum,
230
	}
231
}
232

233
func (p *HeaderValidator) sliceValidator() valueValidator {
234
	return &basicSliceValidator{
235
		Path:         p.name,
236
		In:           "response",
237
		Default:      p.header.Default,
238
		MaxItems:     p.header.MaxItems,
239
		MinItems:     p.header.MinItems,
240
		UniqueItems:  p.header.UniqueItems,
241
		Items:        p.header.Items,
242
		Source:       p.header,
243
		KnownFormats: p.KnownFormats,
244
	}
245
}
246

247
func (p *HeaderValidator) numberValidator() valueValidator {
248
	return &numberValidator{
249
		Path:             p.name,
250
		In:               "response",
251
		Default:          p.header.Default,
252
		MultipleOf:       p.header.MultipleOf,
253
		Maximum:          p.header.Maximum,
254
		ExclusiveMaximum: p.header.ExclusiveMaximum,
255
		Minimum:          p.header.Minimum,
256
		ExclusiveMinimum: p.header.ExclusiveMinimum,
257
		Type:             p.header.Type,
258
		Format:           p.header.Format,
259
	}
260
}
261

262
func (p *HeaderValidator) stringValidator() valueValidator {
263
	return &stringValidator{
264
		Path:            p.name,
265
		In:              "response",
266
		Default:         p.header.Default,
267
		Required:        true,
268
		MaxLength:       p.header.MaxLength,
269
		MinLength:       p.header.MinLength,
270
		Pattern:         p.header.Pattern,
271
		AllowEmptyValue: false,
272
	}
273
}
274

275
func (p *HeaderValidator) formatValidator() valueValidator {
276
	return &formatValidator{
277
		Path: p.name,
278
		In:   "response",
279
		//Default:      p.header.Default,
280
		Format:       p.header.Format,
281
		KnownFormats: p.KnownFormats,
282
	}
283
}
284

285
// A ParamValidator has very limited subset of validations to apply
286
type ParamValidator struct {
287
	param        *spec.Parameter
288
	validators   []valueValidator
289
	KnownFormats strfmt.Registry
290
}
291

292
// NewParamValidator creates a new param validator object
293
func NewParamValidator(param *spec.Parameter, formats strfmt.Registry) *ParamValidator {
294
	p := &ParamValidator{param: param, KnownFormats: formats}
295
	p.validators = []valueValidator{
296
		&typeValidator{
297
			Type:     spec.StringOrArray([]string{param.Type}),
298
			Nullable: param.Nullable,
299
			Format:   param.Format,
300
			In:       param.In,
301
			Path:     param.Name,
302
		},
303
		p.stringValidator(),
304
		p.formatValidator(),
305
		p.numberValidator(),
306
		p.sliceValidator(),
307
		p.commonValidator(),
308
	}
309
	return p
310
}
311

312
// Validate the data against the description of the parameter
313
func (p *ParamValidator) Validate(data interface{}) *Result {
314
	result := new(Result)
315
	tpe := reflect.TypeOf(data)
316
	kind := tpe.Kind()
317

318
	// TODO: validate type
319
	for _, validator := range p.validators {
320
		if validator.Applies(p.param, kind) {
321
			if err := validator.Validate(data); err != nil {
322
				result.Merge(err)
323
				if err.HasErrors() {
324
					return result
325
				}
326
			}
327
		}
328
	}
329
	return nil
330
}
331

332
func (p *ParamValidator) commonValidator() valueValidator {
333
	return &basicCommonValidator{
334
		Path:    p.param.Name,
335
		In:      p.param.In,
336
		Default: p.param.Default,
337
		Enum:    p.param.Enum,
338
	}
339
}
340

341
func (p *ParamValidator) sliceValidator() valueValidator {
342
	return &basicSliceValidator{
343
		Path:         p.param.Name,
344
		In:           p.param.In,
345
		Default:      p.param.Default,
346
		MaxItems:     p.param.MaxItems,
347
		MinItems:     p.param.MinItems,
348
		UniqueItems:  p.param.UniqueItems,
349
		Items:        p.param.Items,
350
		Source:       p.param,
351
		KnownFormats: p.KnownFormats,
352
	}
353
}
354

355
func (p *ParamValidator) numberValidator() valueValidator {
356
	return &numberValidator{
357
		Path:             p.param.Name,
358
		In:               p.param.In,
359
		Default:          p.param.Default,
360
		MultipleOf:       p.param.MultipleOf,
361
		Maximum:          p.param.Maximum,
362
		ExclusiveMaximum: p.param.ExclusiveMaximum,
363
		Minimum:          p.param.Minimum,
364
		ExclusiveMinimum: p.param.ExclusiveMinimum,
365
		Type:             p.param.Type,
366
		Format:           p.param.Format,
367
	}
368
}
369

370
func (p *ParamValidator) stringValidator() valueValidator {
371
	return &stringValidator{
372
		Path:            p.param.Name,
373
		In:              p.param.In,
374
		Default:         p.param.Default,
375
		AllowEmptyValue: p.param.AllowEmptyValue,
376
		Required:        p.param.Required,
377
		MaxLength:       p.param.MaxLength,
378
		MinLength:       p.param.MinLength,
379
		Pattern:         p.param.Pattern,
380
	}
381
}
382

383
func (p *ParamValidator) formatValidator() valueValidator {
384
	return &formatValidator{
385
		Path: p.param.Name,
386
		In:   p.param.In,
387
		//Default:      p.param.Default,
388
		Format:       p.param.Format,
389
		KnownFormats: p.KnownFormats,
390
	}
391
}
392

393
type basicSliceValidator struct {
394
	Path           string
395
	In             string
396
	Default        interface{}
397
	MaxItems       *int64
398
	MinItems       *int64
399
	UniqueItems    bool
400
	Items          *spec.Items
401
	Source         interface{}
402
	itemsValidator *itemsValidator
403
	KnownFormats   strfmt.Registry
404
}
405

406
func (s *basicSliceValidator) SetPath(path string) {
407
	s.Path = path
408
}
409

410
func (s *basicSliceValidator) Applies(source interface{}, kind reflect.Kind) bool {
411
	switch source.(type) {
412
	case *spec.Parameter, *spec.Items, *spec.Header:
413
		return kind == reflect.Slice
414
	}
415
	return false
416
}
417

418
func (s *basicSliceValidator) Validate(data interface{}) *Result {
419
	val := reflect.ValueOf(data)
420

421
	size := int64(val.Len())
422
	if s.MinItems != nil {
423
		if err := MinItems(s.Path, s.In, size, *s.MinItems); err != nil {
424
			return errorHelp.sErr(err)
425
		}
426
	}
427

428
	if s.MaxItems != nil {
429
		if err := MaxItems(s.Path, s.In, size, *s.MaxItems); err != nil {
430
			return errorHelp.sErr(err)
431
		}
432
	}
433

434
	if s.UniqueItems {
435
		if err := UniqueItems(s.Path, s.In, data); err != nil {
436
			return errorHelp.sErr(err)
437
		}
438
	}
439

440
	if s.itemsValidator == nil && s.Items != nil {
441
		s.itemsValidator = newItemsValidator(s.Path, s.In, s.Items, s.Source, s.KnownFormats)
442
	}
443

444
	if s.itemsValidator != nil {
445
		for i := 0; i < int(size); i++ {
446
			ele := val.Index(i)
447
			if err := s.itemsValidator.Validate(i, ele.Interface()); err != nil && err.HasErrors() {
448
				return err
449
			}
450
		}
451
	}
452
	return nil
453
}
454

455
/* unused
456
func (s *basicSliceValidator) hasDuplicates(value reflect.Value, size int) bool {
457
	dict := make(map[interface{}]struct{})
458
	for i := 0; i < size; i++ {
459
		ele := value.Index(i)
460
		if _, ok := dict[ele.Interface()]; ok {
461
			return true
462
		}
463
		dict[ele.Interface()] = struct{}{}
464
	}
465
	return false
466
}
467
*/
468

469
type numberValidator struct {
470
	Path             string
471
	In               string
472
	Default          interface{}
473
	MultipleOf       *float64
474
	Maximum          *float64
475
	ExclusiveMaximum bool
476
	Minimum          *float64
477
	ExclusiveMinimum bool
478
	// Allows for more accurate behavior regarding integers
479
	Type   string
480
	Format string
481
}
482

483
func (n *numberValidator) SetPath(path string) {
484
	n.Path = path
485
}
486

487
func (n *numberValidator) Applies(source interface{}, kind reflect.Kind) bool {
488
	switch source.(type) {
489
	case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
490
		isInt := kind >= reflect.Int && kind <= reflect.Uint64
491
		isFloat := kind == reflect.Float32 || kind == reflect.Float64
492
		r := isInt || isFloat
493
		debugLog("schema props validator for %q applies %t for %T (kind: %v) isInt=%t, isFloat=%t\n", n.Path, r, source, kind, isInt, isFloat)
494
		return r
495
	}
496
	debugLog("schema props validator for %q applies %t for %T (kind: %v)\n", n.Path, false, source, kind)
497
	return false
498
}
499

500
// Validate provides a validator for generic JSON numbers,
501
//
502
// By default, numbers are internally represented as float64.
503
// Formats float, or float32 may alter this behavior by mapping to float32.
504
// A special validation process is followed for integers, with optional "format":
505
// this is an attempt to provide a validation with native types.
506
//
507
// NOTE: since the constraint specified (boundary, multipleOf) is unmarshalled
508
// as float64, loss of information remains possible (e.g. on very large integers).
509
//
510
// Since this value directly comes from the unmarshalling, it is not possible
511
// at this stage of processing to check further and guarantee the correctness of such values.
512
//
513
// Normally, the JSON Number.MAX_SAFE_INTEGER (resp. Number.MIN_SAFE_INTEGER)
514
// would check we do not get such a loss.
515
//
516
// If this is the case, replace AddErrors() by AddWarnings() and IsValid() by !HasWarnings().
517
//
518
// TODO: consider replacing boundary check errors by simple warnings.
519
//
520
// TODO: default boundaries with MAX_SAFE_INTEGER are not checked (specific to json.Number?)
521
func (n *numberValidator) Validate(val interface{}) *Result {
522
	res := new(Result)
523

524
	resMultiple := new(Result)
525
	resMinimum := new(Result)
526
	resMaximum := new(Result)
527

528
	// Used only to attempt to validate constraint on value,
529
	// even though value or constraint specified do not match type and format
530
	data := valueHelp.asFloat64(val)
531

532
	// Is the provided value within the range of the specified numeric type and format?
533
	res.AddErrors(IsValueValidAgainstRange(val, n.Type, n.Format, "Checked", n.Path))
534

535
	if n.MultipleOf != nil {
536
		// Is the constraint specifier within the range of the specific numeric type and format?
537
		resMultiple.AddErrors(IsValueValidAgainstRange(*n.MultipleOf, n.Type, n.Format, "MultipleOf", n.Path))
538
		if resMultiple.IsValid() {
539
			// Constraint validated with compatible types
540
			if err := MultipleOfNativeType(n.Path, n.In, val, *n.MultipleOf); err != nil {
541
				resMultiple.Merge(errorHelp.sErr(err))
542
			}
543
		} else {
544
			// Constraint nevertheless validated, converted as general number
545
			if err := MultipleOf(n.Path, n.In, data, *n.MultipleOf); err != nil {
546
				resMultiple.Merge(errorHelp.sErr(err))
547
			}
548
		}
549
	}
550

551
	// nolint: dupl
552
	if n.Maximum != nil {
553
		// Is the constraint specifier within the range of the specific numeric type and format?
554
		resMaximum.AddErrors(IsValueValidAgainstRange(*n.Maximum, n.Type, n.Format, "Maximum boundary", n.Path))
555
		if resMaximum.IsValid() {
556
			// Constraint validated with compatible types
557
			if err := MaximumNativeType(n.Path, n.In, val, *n.Maximum, n.ExclusiveMaximum); err != nil {
558
				resMaximum.Merge(errorHelp.sErr(err))
559
			}
560
		} else {
561
			// Constraint nevertheless validated, converted as general number
562
			if err := Maximum(n.Path, n.In, data, *n.Maximum, n.ExclusiveMaximum); err != nil {
563
				resMaximum.Merge(errorHelp.sErr(err))
564
			}
565
		}
566
	}
567

568
	// nolint: dupl
569
	if n.Minimum != nil {
570
		// Is the constraint specifier within the range of the specific numeric type and format?
571
		resMinimum.AddErrors(IsValueValidAgainstRange(*n.Minimum, n.Type, n.Format, "Minimum boundary", n.Path))
572
		if resMinimum.IsValid() {
573
			// Constraint validated with compatible types
574
			if err := MinimumNativeType(n.Path, n.In, val, *n.Minimum, n.ExclusiveMinimum); err != nil {
575
				resMinimum.Merge(errorHelp.sErr(err))
576
			}
577
		} else {
578
			// Constraint nevertheless validated, converted as general number
579
			if err := Minimum(n.Path, n.In, data, *n.Minimum, n.ExclusiveMinimum); err != nil {
580
				resMinimum.Merge(errorHelp.sErr(err))
581
			}
582
		}
583
	}
584
	res.Merge(resMultiple, resMinimum, resMaximum)
585
	res.Inc()
586
	return res
587
}
588

589
type stringValidator struct {
590
	Default         interface{}
591
	Required        bool
592
	AllowEmptyValue bool
593
	MaxLength       *int64
594
	MinLength       *int64
595
	Pattern         string
596
	Path            string
597
	In              string
598
}
599

600
func (s *stringValidator) SetPath(path string) {
601
	s.Path = path
602
}
603

604
func (s *stringValidator) Applies(source interface{}, kind reflect.Kind) bool {
605
	switch source.(type) {
606
	case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
607
		r := kind == reflect.String
608
		debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, r, source, kind)
609
		return r
610
	}
611
	debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, false, source, kind)
612
	return false
613
}
614

615
func (s *stringValidator) Validate(val interface{}) *Result {
616
	data, ok := val.(string)
617
	if !ok {
618
		return errorHelp.sErr(errors.InvalidType(s.Path, s.In, stringType, val))
619
	}
620

621
	if s.Required && !s.AllowEmptyValue && (s.Default == nil || s.Default == "") {
622
		if err := RequiredString(s.Path, s.In, data); err != nil {
623
			return errorHelp.sErr(err)
624
		}
625
	}
626

627
	if s.MaxLength != nil {
628
		if err := MaxLength(s.Path, s.In, data, *s.MaxLength); err != nil {
629
			return errorHelp.sErr(err)
630
		}
631
	}
632

633
	if s.MinLength != nil {
634
		if err := MinLength(s.Path, s.In, data, *s.MinLength); err != nil {
635
			return errorHelp.sErr(err)
636
		}
637
	}
638

639
	if s.Pattern != "" {
640
		if err := Pattern(s.Path, s.In, data, s.Pattern); err != nil {
641
			return errorHelp.sErr(err)
642
		}
643
	}
644
	return nil
645
}
646

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

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

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

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