1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package validate
16
17 import (
18 "context"
19 "fmt"
20 "reflect"
21 "strings"
22 "unicode/utf8"
23
24 "github.com/go-openapi/errors"
25 "github.com/go-openapi/strfmt"
26 "github.com/go-openapi/swag"
27 )
28
29
30 func Enum(path, in string, data interface{}, enum interface{}) *errors.Validation {
31 return EnumCase(path, in, data, enum, true)
32 }
33
34
35 func EnumCase(path, in string, data interface{}, enum interface{}, caseSensitive bool) *errors.Validation {
36 val := reflect.ValueOf(enum)
37 if val.Kind() != reflect.Slice {
38 return nil
39 }
40
41 dataString := convertEnumCaseStringKind(data, caseSensitive)
42 var values []interface{}
43 for i := 0; i < val.Len(); i++ {
44 ele := val.Index(i)
45 enumValue := ele.Interface()
46 if data != nil {
47 if reflect.DeepEqual(data, enumValue) {
48 return nil
49 }
50 enumString := convertEnumCaseStringKind(enumValue, caseSensitive)
51 if dataString != nil && enumString != nil && strings.EqualFold(*dataString, *enumString) {
52 return nil
53 }
54 actualType := reflect.TypeOf(enumValue)
55 if actualType == nil {
56 continue
57 }
58 expectedValue := reflect.ValueOf(data)
59 if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
60
61 if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
62 return nil
63 }
64 }
65 }
66 values = append(values, enumValue)
67 }
68 return errors.EnumFail(path, in, data, values)
69 }
70
71
72 func convertEnumCaseStringKind(value interface{}, caseSensitive bool) *string {
73 if caseSensitive {
74 return nil
75 }
76
77 val := reflect.ValueOf(value)
78 if val.Kind() != reflect.String {
79 return nil
80 }
81
82 str := fmt.Sprintf("%v", value)
83 return &str
84 }
85
86
87 func MinItems(path, in string, size, min int64) *errors.Validation {
88 if size < min {
89 return errors.TooFewItems(path, in, min, size)
90 }
91 return nil
92 }
93
94
95 func MaxItems(path, in string, size, max int64) *errors.Validation {
96 if size > max {
97 return errors.TooManyItems(path, in, max, size)
98 }
99 return nil
100 }
101
102
103 func UniqueItems(path, in string, data interface{}) *errors.Validation {
104 val := reflect.ValueOf(data)
105 if val.Kind() != reflect.Slice {
106 return nil
107 }
108 var unique []interface{}
109 for i := 0; i < val.Len(); i++ {
110 v := val.Index(i).Interface()
111 for _, u := range unique {
112 if reflect.DeepEqual(v, u) {
113 return errors.DuplicateItems(path, in)
114 }
115 }
116 unique = append(unique, v)
117 }
118 return nil
119 }
120
121
122 func MinLength(path, in, data string, minLength int64) *errors.Validation {
123 strLen := int64(utf8.RuneCountInString(data))
124 if strLen < minLength {
125 return errors.TooShort(path, in, minLength, data)
126 }
127 return nil
128 }
129
130
131 func MaxLength(path, in, data string, maxLength int64) *errors.Validation {
132 strLen := int64(utf8.RuneCountInString(data))
133 if strLen > maxLength {
134 return errors.TooLong(path, in, maxLength, data)
135 }
136 return nil
137 }
138
139
140 func ReadOnly(ctx context.Context, path, in string, data interface{}) *errors.Validation {
141
142
143 if op := extractOperationType(ctx); op != request {
144 return nil
145 }
146
147
148 val := reflect.ValueOf(data)
149 if val.IsValid() {
150 if reflect.DeepEqual(reflect.Zero(val.Type()).Interface(), val.Interface()) {
151 return nil
152 }
153 } else {
154 return nil
155 }
156
157 return errors.ReadOnly(path, in, data)
158 }
159
160
161 func Required(path, in string, data interface{}) *errors.Validation {
162 val := reflect.ValueOf(data)
163 if val.IsValid() {
164 if reflect.DeepEqual(reflect.Zero(val.Type()).Interface(), val.Interface()) {
165 return errors.Required(path, in, data)
166 }
167 return nil
168 }
169 return errors.Required(path, in, data)
170 }
171
172
173 func RequiredString(path, in, data string) *errors.Validation {
174 if data == "" {
175 return errors.Required(path, in, data)
176 }
177 return nil
178 }
179
180
181 func RequiredNumber(path, in string, data float64) *errors.Validation {
182 if data == 0 {
183 return errors.Required(path, in, data)
184 }
185 return nil
186 }
187
188
189 func Pattern(path, in, data, pattern string) *errors.Validation {
190 re, err := compileRegexp(pattern)
191 if err != nil {
192 return errors.FailedPattern(path, in, fmt.Sprintf("%s, but pattern is invalid: %s", pattern, err.Error()), data)
193 }
194 if !re.MatchString(data) {
195 return errors.FailedPattern(path, in, pattern, data)
196 }
197 return nil
198 }
199
200
201 func MaximumInt(path, in string, data, max int64, exclusive bool) *errors.Validation {
202 if (!exclusive && data > max) || (exclusive && data >= max) {
203 return errors.ExceedsMaximumInt(path, in, max, exclusive, data)
204 }
205 return nil
206 }
207
208
209 func MaximumUint(path, in string, data, max uint64, exclusive bool) *errors.Validation {
210 if (!exclusive && data > max) || (exclusive && data >= max) {
211 return errors.ExceedsMaximumUint(path, in, max, exclusive, data)
212 }
213 return nil
214 }
215
216
217 func Maximum(path, in string, data, max float64, exclusive bool) *errors.Validation {
218 if (!exclusive && data > max) || (exclusive && data >= max) {
219 return errors.ExceedsMaximum(path, in, max, exclusive, data)
220 }
221 return nil
222 }
223
224
225 func Minimum(path, in string, data, min float64, exclusive bool) *errors.Validation {
226 if (!exclusive && data < min) || (exclusive && data <= min) {
227 return errors.ExceedsMinimum(path, in, min, exclusive, data)
228 }
229 return nil
230 }
231
232
233 func MinimumInt(path, in string, data, min int64, exclusive bool) *errors.Validation {
234 if (!exclusive && data < min) || (exclusive && data <= min) {
235 return errors.ExceedsMinimumInt(path, in, min, exclusive, data)
236 }
237 return nil
238 }
239
240
241 func MinimumUint(path, in string, data, min uint64, exclusive bool) *errors.Validation {
242 if (!exclusive && data < min) || (exclusive && data <= min) {
243 return errors.ExceedsMinimumUint(path, in, min, exclusive, data)
244 }
245 return nil
246 }
247
248
249 func MultipleOf(path, in string, data, factor float64) *errors.Validation {
250
251 if factor <= 0 {
252 return errors.MultipleOfMustBePositive(path, in, factor)
253 }
254 var mult float64
255 if factor < 1 {
256 mult = 1 / factor * data
257 } else {
258 mult = data / factor
259 }
260 if !swag.IsFloat64AJSONInteger(mult) {
261 return errors.NotMultipleOf(path, in, factor, data)
262 }
263 return nil
264 }
265
266
267 func MultipleOfInt(path, in string, data int64, factor int64) *errors.Validation {
268
269 if factor <= 0 {
270 return errors.MultipleOfMustBePositive(path, in, factor)
271 }
272 mult := data / factor
273 if mult*factor != data {
274 return errors.NotMultipleOf(path, in, factor, data)
275 }
276 return nil
277 }
278
279
280 func MultipleOfUint(path, in string, data, factor uint64) *errors.Validation {
281
282 if factor == 0 {
283 return errors.MultipleOfMustBePositive(path, in, factor)
284 }
285 mult := data / factor
286 if mult*factor != data {
287 return errors.NotMultipleOf(path, in, factor, data)
288 }
289 return nil
290 }
291
292
293 func FormatOf(path, in, format, data string, registry strfmt.Registry) *errors.Validation {
294 if registry == nil {
295 registry = strfmt.Default
296 }
297 if ok := registry.ContainsName(format); !ok {
298 return errors.InvalidTypeName(format)
299 }
300 if ok := registry.Validates(format, data); !ok {
301 return errors.InvalidType(path, in, format, data)
302 }
303 return nil
304 }
305
306
307
308
309
310
311
312
313
314
315
316 func MaximumNativeType(path, in string, val interface{}, max float64, exclusive bool) *errors.Validation {
317 kind := reflect.ValueOf(val).Type().Kind()
318 switch kind {
319 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
320 value := valueHelp.asInt64(val)
321 return MaximumInt(path, in, value, int64(max), exclusive)
322 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
323 value := valueHelp.asUint64(val)
324 if max < 0 {
325 return errors.ExceedsMaximum(path, in, max, exclusive, val)
326 }
327 return MaximumUint(path, in, value, uint64(max), exclusive)
328 case reflect.Float32, reflect.Float64:
329 fallthrough
330 default:
331 value := valueHelp.asFloat64(val)
332 return Maximum(path, in, value, max, exclusive)
333 }
334 }
335
336
337
338
339
340
341
342
343
344
345
346 func MinimumNativeType(path, in string, val interface{}, min float64, exclusive bool) *errors.Validation {
347 kind := reflect.ValueOf(val).Type().Kind()
348 switch kind {
349 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
350 value := valueHelp.asInt64(val)
351 return MinimumInt(path, in, value, int64(min), exclusive)
352 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
353 value := valueHelp.asUint64(val)
354 if min < 0 {
355 return nil
356 }
357 return MinimumUint(path, in, value, uint64(min), exclusive)
358 case reflect.Float32, reflect.Float64:
359 fallthrough
360 default:
361 value := valueHelp.asFloat64(val)
362 return Minimum(path, in, value, min, exclusive)
363 }
364 }
365
366
367
368
369
370
371
372
373
374
375
376 func MultipleOfNativeType(path, in string, val interface{}, multipleOf float64) *errors.Validation {
377 kind := reflect.ValueOf(val).Type().Kind()
378 switch kind {
379 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
380 value := valueHelp.asInt64(val)
381 return MultipleOfInt(path, in, value, int64(multipleOf))
382 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
383 value := valueHelp.asUint64(val)
384 return MultipleOfUint(path, in, value, uint64(multipleOf))
385 case reflect.Float32, reflect.Float64:
386 fallthrough
387 default:
388 value := valueHelp.asFloat64(val)
389 return MultipleOf(path, in, value, multipleOf)
390 }
391 }
392
393
394
395
396
397 func IsValueValidAgainstRange(val interface{}, typeName, format, prefix, path string) error {
398 kind := reflect.ValueOf(val).Type().Kind()
399
400
401 var stringRep string
402 switch kind {
403 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
404 stringRep = swag.FormatUint64(valueHelp.asUint64(val))
405 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
406 stringRep = swag.FormatInt64(valueHelp.asInt64(val))
407 case reflect.Float32, reflect.Float64:
408 stringRep = swag.FormatFloat64(valueHelp.asFloat64(val))
409 default:
410 return fmt.Errorf("%s value number range checking called with invalid (non numeric) val type in %s", prefix, path)
411 }
412
413 var errVal error
414
415 switch typeName {
416 case integerType:
417 switch format {
418 case integerFormatInt32:
419 _, errVal = swag.ConvertInt32(stringRep)
420 case integerFormatUInt32:
421 _, errVal = swag.ConvertUint32(stringRep)
422 case integerFormatUInt64:
423 _, errVal = swag.ConvertUint64(stringRep)
424 case integerFormatInt64:
425 fallthrough
426 default:
427 _, errVal = swag.ConvertInt64(stringRep)
428 }
429 case numberType:
430 fallthrough
431 default:
432 switch format {
433 case numberFormatFloat, numberFormatFloat32:
434 _, errVal = swag.ConvertFloat32(stringRep)
435 case numberFormatDouble, numberFormatFloat64:
436 fallthrough
437 default:
438
439
440 }
441 }
442 if errVal != nil {
443 if format != "" {
444 errVal = fmt.Errorf("%s value must be of type %s with format %s in %s", prefix, typeName, format, path)
445 } else {
446 errVal = fmt.Errorf("%s value must be of type %s (default format) in %s", prefix, typeName, path)
447 }
448 }
449 return errVal
450 }
451
View as plain text