You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

validator.go 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  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. package validate
  15. import (
  16. "fmt"
  17. "reflect"
  18. "github.com/go-openapi/errors"
  19. "github.com/go-openapi/spec"
  20. "github.com/go-openapi/strfmt"
  21. )
  22. // An EntityValidator is an interface for things that can validate entities
  23. type EntityValidator interface {
  24. Validate(interface{}) *Result
  25. }
  26. type valueValidator interface {
  27. SetPath(path string)
  28. Applies(interface{}, reflect.Kind) bool
  29. Validate(interface{}) *Result
  30. }
  31. type itemsValidator struct {
  32. items *spec.Items
  33. root interface{}
  34. path string
  35. in string
  36. validators []valueValidator
  37. KnownFormats strfmt.Registry
  38. }
  39. func newItemsValidator(path, in string, items *spec.Items, root interface{}, formats strfmt.Registry) *itemsValidator {
  40. iv := &itemsValidator{path: path, in: in, items: items, root: root, KnownFormats: formats}
  41. iv.validators = []valueValidator{
  42. &typeValidator{
  43. Type: spec.StringOrArray([]string{items.Type}),
  44. Nullable: items.Nullable,
  45. Format: items.Format,
  46. In: in,
  47. Path: path,
  48. },
  49. iv.stringValidator(),
  50. iv.formatValidator(),
  51. iv.numberValidator(),
  52. iv.sliceValidator(),
  53. iv.commonValidator(),
  54. }
  55. return iv
  56. }
  57. func (i *itemsValidator) Validate(index int, data interface{}) *Result {
  58. tpe := reflect.TypeOf(data)
  59. kind := tpe.Kind()
  60. mainResult := new(Result)
  61. path := fmt.Sprintf("%s.%d", i.path, index)
  62. for _, validator := range i.validators {
  63. validator.SetPath(path)
  64. if validator.Applies(i.root, kind) {
  65. result := validator.Validate(data)
  66. mainResult.Merge(result)
  67. mainResult.Inc()
  68. if result != nil && result.HasErrors() {
  69. return mainResult
  70. }
  71. }
  72. }
  73. return mainResult
  74. }
  75. func (i *itemsValidator) commonValidator() valueValidator {
  76. return &basicCommonValidator{
  77. In: i.in,
  78. Default: i.items.Default,
  79. Enum: i.items.Enum,
  80. }
  81. }
  82. func (i *itemsValidator) sliceValidator() valueValidator {
  83. return &basicSliceValidator{
  84. In: i.in,
  85. Default: i.items.Default,
  86. MaxItems: i.items.MaxItems,
  87. MinItems: i.items.MinItems,
  88. UniqueItems: i.items.UniqueItems,
  89. Source: i.root,
  90. Items: i.items.Items,
  91. KnownFormats: i.KnownFormats,
  92. }
  93. }
  94. func (i *itemsValidator) numberValidator() valueValidator {
  95. return &numberValidator{
  96. In: i.in,
  97. Default: i.items.Default,
  98. MultipleOf: i.items.MultipleOf,
  99. Maximum: i.items.Maximum,
  100. ExclusiveMaximum: i.items.ExclusiveMaximum,
  101. Minimum: i.items.Minimum,
  102. ExclusiveMinimum: i.items.ExclusiveMinimum,
  103. Type: i.items.Type,
  104. Format: i.items.Format,
  105. }
  106. }
  107. func (i *itemsValidator) stringValidator() valueValidator {
  108. return &stringValidator{
  109. In: i.in,
  110. Default: i.items.Default,
  111. MaxLength: i.items.MaxLength,
  112. MinLength: i.items.MinLength,
  113. Pattern: i.items.Pattern,
  114. AllowEmptyValue: false,
  115. }
  116. }
  117. func (i *itemsValidator) formatValidator() valueValidator {
  118. return &formatValidator{
  119. In: i.in,
  120. //Default: i.items.Default,
  121. Format: i.items.Format,
  122. KnownFormats: i.KnownFormats,
  123. }
  124. }
  125. type basicCommonValidator struct {
  126. Path string
  127. In string
  128. Default interface{}
  129. Enum []interface{}
  130. }
  131. func (b *basicCommonValidator) SetPath(path string) {
  132. b.Path = path
  133. }
  134. func (b *basicCommonValidator) Applies(source interface{}, kind reflect.Kind) bool {
  135. switch source.(type) {
  136. case *spec.Parameter, *spec.Schema, *spec.Header:
  137. return true
  138. }
  139. return false
  140. }
  141. func (b *basicCommonValidator) Validate(data interface{}) (res *Result) {
  142. if len(b.Enum) > 0 {
  143. for _, enumValue := range b.Enum {
  144. actualType := reflect.TypeOf(enumValue)
  145. if actualType != nil { // Safeguard
  146. expectedValue := reflect.ValueOf(data)
  147. if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
  148. if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
  149. return nil
  150. }
  151. }
  152. }
  153. }
  154. return errorHelp.sErr(errors.EnumFail(b.Path, b.In, data, b.Enum))
  155. }
  156. return nil
  157. }
  158. // A HeaderValidator has very limited subset of validations to apply
  159. type HeaderValidator struct {
  160. name string
  161. header *spec.Header
  162. validators []valueValidator
  163. KnownFormats strfmt.Registry
  164. }
  165. // NewHeaderValidator creates a new header validator object
  166. func NewHeaderValidator(name string, header *spec.Header, formats strfmt.Registry) *HeaderValidator {
  167. p := &HeaderValidator{name: name, header: header, KnownFormats: formats}
  168. p.validators = []valueValidator{
  169. &typeValidator{
  170. Type: spec.StringOrArray([]string{header.Type}),
  171. Nullable: header.Nullable,
  172. Format: header.Format,
  173. In: "header",
  174. Path: name,
  175. },
  176. p.stringValidator(),
  177. p.formatValidator(),
  178. p.numberValidator(),
  179. p.sliceValidator(),
  180. p.commonValidator(),
  181. }
  182. return p
  183. }
  184. // Validate the value of the header against its schema
  185. func (p *HeaderValidator) Validate(data interface{}) *Result {
  186. result := new(Result)
  187. tpe := reflect.TypeOf(data)
  188. kind := tpe.Kind()
  189. for _, validator := range p.validators {
  190. if validator.Applies(p.header, kind) {
  191. if err := validator.Validate(data); err != nil {
  192. result.Merge(err)
  193. if err.HasErrors() {
  194. return result
  195. }
  196. }
  197. }
  198. }
  199. return nil
  200. }
  201. func (p *HeaderValidator) commonValidator() valueValidator {
  202. return &basicCommonValidator{
  203. Path: p.name,
  204. In: "response",
  205. Default: p.header.Default,
  206. Enum: p.header.Enum,
  207. }
  208. }
  209. func (p *HeaderValidator) sliceValidator() valueValidator {
  210. return &basicSliceValidator{
  211. Path: p.name,
  212. In: "response",
  213. Default: p.header.Default,
  214. MaxItems: p.header.MaxItems,
  215. MinItems: p.header.MinItems,
  216. UniqueItems: p.header.UniqueItems,
  217. Items: p.header.Items,
  218. Source: p.header,
  219. KnownFormats: p.KnownFormats,
  220. }
  221. }
  222. func (p *HeaderValidator) numberValidator() valueValidator {
  223. return &numberValidator{
  224. Path: p.name,
  225. In: "response",
  226. Default: p.header.Default,
  227. MultipleOf: p.header.MultipleOf,
  228. Maximum: p.header.Maximum,
  229. ExclusiveMaximum: p.header.ExclusiveMaximum,
  230. Minimum: p.header.Minimum,
  231. ExclusiveMinimum: p.header.ExclusiveMinimum,
  232. Type: p.header.Type,
  233. Format: p.header.Format,
  234. }
  235. }
  236. func (p *HeaderValidator) stringValidator() valueValidator {
  237. return &stringValidator{
  238. Path: p.name,
  239. In: "response",
  240. Default: p.header.Default,
  241. Required: true,
  242. MaxLength: p.header.MaxLength,
  243. MinLength: p.header.MinLength,
  244. Pattern: p.header.Pattern,
  245. AllowEmptyValue: false,
  246. }
  247. }
  248. func (p *HeaderValidator) formatValidator() valueValidator {
  249. return &formatValidator{
  250. Path: p.name,
  251. In: "response",
  252. //Default: p.header.Default,
  253. Format: p.header.Format,
  254. KnownFormats: p.KnownFormats,
  255. }
  256. }
  257. // A ParamValidator has very limited subset of validations to apply
  258. type ParamValidator struct {
  259. param *spec.Parameter
  260. validators []valueValidator
  261. KnownFormats strfmt.Registry
  262. }
  263. // NewParamValidator creates a new param validator object
  264. func NewParamValidator(param *spec.Parameter, formats strfmt.Registry) *ParamValidator {
  265. p := &ParamValidator{param: param, KnownFormats: formats}
  266. p.validators = []valueValidator{
  267. &typeValidator{
  268. Type: spec.StringOrArray([]string{param.Type}),
  269. Nullable: param.Nullable,
  270. Format: param.Format,
  271. In: param.In,
  272. Path: param.Name,
  273. },
  274. p.stringValidator(),
  275. p.formatValidator(),
  276. p.numberValidator(),
  277. p.sliceValidator(),
  278. p.commonValidator(),
  279. }
  280. return p
  281. }
  282. // Validate the data against the description of the parameter
  283. func (p *ParamValidator) Validate(data interface{}) *Result {
  284. result := new(Result)
  285. tpe := reflect.TypeOf(data)
  286. kind := tpe.Kind()
  287. // TODO: validate type
  288. for _, validator := range p.validators {
  289. if validator.Applies(p.param, kind) {
  290. if err := validator.Validate(data); err != nil {
  291. result.Merge(err)
  292. if err.HasErrors() {
  293. return result
  294. }
  295. }
  296. }
  297. }
  298. return nil
  299. }
  300. func (p *ParamValidator) commonValidator() valueValidator {
  301. return &basicCommonValidator{
  302. Path: p.param.Name,
  303. In: p.param.In,
  304. Default: p.param.Default,
  305. Enum: p.param.Enum,
  306. }
  307. }
  308. func (p *ParamValidator) sliceValidator() valueValidator {
  309. return &basicSliceValidator{
  310. Path: p.param.Name,
  311. In: p.param.In,
  312. Default: p.param.Default,
  313. MaxItems: p.param.MaxItems,
  314. MinItems: p.param.MinItems,
  315. UniqueItems: p.param.UniqueItems,
  316. Items: p.param.Items,
  317. Source: p.param,
  318. KnownFormats: p.KnownFormats,
  319. }
  320. }
  321. func (p *ParamValidator) numberValidator() valueValidator {
  322. return &numberValidator{
  323. Path: p.param.Name,
  324. In: p.param.In,
  325. Default: p.param.Default,
  326. MultipleOf: p.param.MultipleOf,
  327. Maximum: p.param.Maximum,
  328. ExclusiveMaximum: p.param.ExclusiveMaximum,
  329. Minimum: p.param.Minimum,
  330. ExclusiveMinimum: p.param.ExclusiveMinimum,
  331. Type: p.param.Type,
  332. Format: p.param.Format,
  333. }
  334. }
  335. func (p *ParamValidator) stringValidator() valueValidator {
  336. return &stringValidator{
  337. Path: p.param.Name,
  338. In: p.param.In,
  339. Default: p.param.Default,
  340. AllowEmptyValue: p.param.AllowEmptyValue,
  341. Required: p.param.Required,
  342. MaxLength: p.param.MaxLength,
  343. MinLength: p.param.MinLength,
  344. Pattern: p.param.Pattern,
  345. }
  346. }
  347. func (p *ParamValidator) formatValidator() valueValidator {
  348. return &formatValidator{
  349. Path: p.param.Name,
  350. In: p.param.In,
  351. //Default: p.param.Default,
  352. Format: p.param.Format,
  353. KnownFormats: p.KnownFormats,
  354. }
  355. }
  356. type basicSliceValidator struct {
  357. Path string
  358. In string
  359. Default interface{}
  360. MaxItems *int64
  361. MinItems *int64
  362. UniqueItems bool
  363. Items *spec.Items
  364. Source interface{}
  365. itemsValidator *itemsValidator
  366. KnownFormats strfmt.Registry
  367. }
  368. func (s *basicSliceValidator) SetPath(path string) {
  369. s.Path = path
  370. }
  371. func (s *basicSliceValidator) Applies(source interface{}, kind reflect.Kind) bool {
  372. switch source.(type) {
  373. case *spec.Parameter, *spec.Items, *spec.Header:
  374. return kind == reflect.Slice
  375. }
  376. return false
  377. }
  378. func (s *basicSliceValidator) Validate(data interface{}) *Result {
  379. val := reflect.ValueOf(data)
  380. size := int64(val.Len())
  381. if s.MinItems != nil {
  382. if err := MinItems(s.Path, s.In, size, *s.MinItems); err != nil {
  383. return errorHelp.sErr(err)
  384. }
  385. }
  386. if s.MaxItems != nil {
  387. if err := MaxItems(s.Path, s.In, size, *s.MaxItems); err != nil {
  388. return errorHelp.sErr(err)
  389. }
  390. }
  391. if s.UniqueItems {
  392. if err := UniqueItems(s.Path, s.In, data); err != nil {
  393. return errorHelp.sErr(err)
  394. }
  395. }
  396. if s.itemsValidator == nil && s.Items != nil {
  397. s.itemsValidator = newItemsValidator(s.Path, s.In, s.Items, s.Source, s.KnownFormats)
  398. }
  399. if s.itemsValidator != nil {
  400. for i := 0; i < int(size); i++ {
  401. ele := val.Index(i)
  402. if err := s.itemsValidator.Validate(i, ele.Interface()); err != nil && err.HasErrors() {
  403. return err
  404. }
  405. }
  406. }
  407. return nil
  408. }
  409. func (s *basicSliceValidator) hasDuplicates(value reflect.Value, size int) bool {
  410. dict := make(map[interface{}]struct{})
  411. for i := 0; i < size; i++ {
  412. ele := value.Index(i)
  413. if _, ok := dict[ele.Interface()]; ok {
  414. return true
  415. }
  416. dict[ele.Interface()] = struct{}{}
  417. }
  418. return false
  419. }
  420. type numberValidator struct {
  421. Path string
  422. In string
  423. Default interface{}
  424. MultipleOf *float64
  425. Maximum *float64
  426. ExclusiveMaximum bool
  427. Minimum *float64
  428. ExclusiveMinimum bool
  429. // Allows for more accurate behavior regarding integers
  430. Type string
  431. Format string
  432. }
  433. func (n *numberValidator) SetPath(path string) {
  434. n.Path = path
  435. }
  436. func (n *numberValidator) Applies(source interface{}, kind reflect.Kind) bool {
  437. switch source.(type) {
  438. case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
  439. isInt := kind >= reflect.Int && kind <= reflect.Uint64
  440. isFloat := kind == reflect.Float32 || kind == reflect.Float64
  441. r := isInt || isFloat
  442. debugLog("schema props validator for %q applies %t for %T (kind: %v) isInt=%t, isFloat=%t\n", n.Path, r, source, kind, isInt, isFloat)
  443. return r
  444. }
  445. debugLog("schema props validator for %q applies %t for %T (kind: %v)\n", n.Path, false, source, kind)
  446. return false
  447. }
  448. // Validate provides a validator for generic JSON numbers,
  449. //
  450. // By default, numbers are internally represented as float64.
  451. // Formats float, or float32 may alter this behavior by mapping to float32.
  452. // A special validation process is followed for integers, with optional "format":
  453. // this is an attempt to provide a validation with native types.
  454. //
  455. // NOTE: since the constraint specified (boundary, multipleOf) is unmarshalled
  456. // as float64, loss of information remains possible (e.g. on very large integers).
  457. //
  458. // Since this value directly comes from the unmarshalling, it is not possible
  459. // at this stage of processing to check further and guarantee the correctness of such values.
  460. //
  461. // Normally, the JSON Number.MAX_SAFE_INTEGER (resp. Number.MIN_SAFE_INTEGER)
  462. // would check we do not get such a loss.
  463. //
  464. // If this is the case, replace AddErrors() by AddWarnings() and IsValid() by !HasWarnings().
  465. //
  466. // TODO: consider replacing boundary check errors by simple warnings.
  467. //
  468. // TODO: default boundaries with MAX_SAFE_INTEGER are not checked (specific to json.Number?)
  469. func (n *numberValidator) Validate(val interface{}) *Result {
  470. res := new(Result)
  471. resMultiple := new(Result)
  472. resMinimum := new(Result)
  473. resMaximum := new(Result)
  474. // Used only to attempt to validate constraint on value,
  475. // even though value or constraint specified do not match type and format
  476. data := valueHelp.asFloat64(val)
  477. // Is the provided value within the range of the specified numeric type and format?
  478. res.AddErrors(IsValueValidAgainstRange(val, n.Type, n.Format, "Checked", n.Path))
  479. if n.MultipleOf != nil {
  480. // Is the constraint specifier within the range of the specific numeric type and format?
  481. resMultiple.AddErrors(IsValueValidAgainstRange(*n.MultipleOf, n.Type, n.Format, "MultipleOf", n.Path))
  482. if resMultiple.IsValid() {
  483. // Constraint validated with compatible types
  484. if err := MultipleOfNativeType(n.Path, n.In, val, *n.MultipleOf); err != nil {
  485. resMultiple.Merge(errorHelp.sErr(err))
  486. }
  487. } else {
  488. // Constraint nevertheless validated, converted as general number
  489. if err := MultipleOf(n.Path, n.In, data, *n.MultipleOf); err != nil {
  490. resMultiple.Merge(errorHelp.sErr(err))
  491. }
  492. }
  493. }
  494. if n.Maximum != nil {
  495. // Is the constraint specifier within the range of the specific numeric type and format?
  496. resMaximum.AddErrors(IsValueValidAgainstRange(*n.Maximum, n.Type, n.Format, "Maximum boundary", n.Path))
  497. if resMaximum.IsValid() {
  498. // Constraint validated with compatible types
  499. if err := MaximumNativeType(n.Path, n.In, val, *n.Maximum, n.ExclusiveMaximum); err != nil {
  500. resMaximum.Merge(errorHelp.sErr(err))
  501. }
  502. } else {
  503. // Constraint nevertheless validated, converted as general number
  504. if err := Maximum(n.Path, n.In, data, *n.Maximum, n.ExclusiveMaximum); err != nil {
  505. resMaximum.Merge(errorHelp.sErr(err))
  506. }
  507. }
  508. }
  509. if n.Minimum != nil {
  510. // Is the constraint specifier within the range of the specific numeric type and format?
  511. resMinimum.AddErrors(IsValueValidAgainstRange(*n.Minimum, n.Type, n.Format, "Minimum boundary", n.Path))
  512. if resMinimum.IsValid() {
  513. // Constraint validated with compatible types
  514. if err := MinimumNativeType(n.Path, n.In, val, *n.Minimum, n.ExclusiveMinimum); err != nil {
  515. resMinimum.Merge(errorHelp.sErr(err))
  516. }
  517. } else {
  518. // Constraint nevertheless validated, converted as general number
  519. if err := Minimum(n.Path, n.In, data, *n.Minimum, n.ExclusiveMinimum); err != nil {
  520. resMinimum.Merge(errorHelp.sErr(err))
  521. }
  522. }
  523. }
  524. res.Merge(resMultiple, resMinimum, resMaximum)
  525. res.Inc()
  526. return res
  527. }
  528. type stringValidator struct {
  529. Default interface{}
  530. Required bool
  531. AllowEmptyValue bool
  532. MaxLength *int64
  533. MinLength *int64
  534. Pattern string
  535. Path string
  536. In string
  537. }
  538. func (s *stringValidator) SetPath(path string) {
  539. s.Path = path
  540. }
  541. func (s *stringValidator) Applies(source interface{}, kind reflect.Kind) bool {
  542. switch source.(type) {
  543. case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
  544. r := kind == reflect.String
  545. debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, r, source, kind)
  546. return r
  547. }
  548. debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, false, source, kind)
  549. return false
  550. }
  551. func (s *stringValidator) Validate(val interface{}) *Result {
  552. data, ok := val.(string)
  553. if !ok {
  554. return errorHelp.sErr(errors.InvalidType(s.Path, s.In, "string", val))
  555. }
  556. if s.Required && !s.AllowEmptyValue && (s.Default == nil || s.Default == "") {
  557. if err := RequiredString(s.Path, s.In, data); err != nil {
  558. return errorHelp.sErr(err)
  559. }
  560. }
  561. if s.MaxLength != nil {
  562. if err := MaxLength(s.Path, s.In, data, *s.MaxLength); err != nil {
  563. return errorHelp.sErr(err)
  564. }
  565. }
  566. if s.MinLength != nil {
  567. if err := MinLength(s.Path, s.In, data, *s.MinLength); err != nil {
  568. return errorHelp.sErr(err)
  569. }
  570. }
  571. if s.Pattern != "" {
  572. if err := Pattern(s.Path, s.In, data, s.Pattern); err != nil {
  573. return errorHelp.sErr(err)
  574. }
  575. }
  576. return nil
  577. }