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.

schema.go 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  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 errors
  15. import (
  16. "fmt"
  17. "strings"
  18. )
  19. const (
  20. invalidType = "%s is an invalid type name"
  21. typeFail = "%s in %s must be of type %s"
  22. typeFailWithData = "%s in %s must be of type %s: %q"
  23. typeFailWithError = "%s in %s must be of type %s, because: %s"
  24. requiredFail = "%s in %s is required"
  25. tooLongMessage = "%s in %s should be at most %d chars long"
  26. tooShortMessage = "%s in %s should be at least %d chars long"
  27. patternFail = "%s in %s should match '%s'"
  28. enumFail = "%s in %s should be one of %v"
  29. multipleOfFail = "%s in %s should be a multiple of %v"
  30. maxIncFail = "%s in %s should be less than or equal to %v"
  31. maxExcFail = "%s in %s should be less than %v"
  32. minIncFail = "%s in %s should be greater than or equal to %v"
  33. minExcFail = "%s in %s should be greater than %v"
  34. uniqueFail = "%s in %s shouldn't contain duplicates"
  35. maxItemsFail = "%s in %s should have at most %d items"
  36. minItemsFail = "%s in %s should have at least %d items"
  37. typeFailNoIn = "%s must be of type %s"
  38. typeFailWithDataNoIn = "%s must be of type %s: %q"
  39. typeFailWithErrorNoIn = "%s must be of type %s, because: %s"
  40. requiredFailNoIn = "%s is required"
  41. tooLongMessageNoIn = "%s should be at most %d chars long"
  42. tooShortMessageNoIn = "%s should be at least %d chars long"
  43. patternFailNoIn = "%s should match '%s'"
  44. enumFailNoIn = "%s should be one of %v"
  45. multipleOfFailNoIn = "%s should be a multiple of %v"
  46. maxIncFailNoIn = "%s should be less than or equal to %v"
  47. maxExcFailNoIn = "%s should be less than %v"
  48. minIncFailNoIn = "%s should be greater than or equal to %v"
  49. minExcFailNoIn = "%s should be greater than %v"
  50. uniqueFailNoIn = "%s shouldn't contain duplicates"
  51. maxItemsFailNoIn = "%s should have at most %d items"
  52. minItemsFailNoIn = "%s should have at least %d items"
  53. noAdditionalItems = "%s in %s can't have additional items"
  54. noAdditionalItemsNoIn = "%s can't have additional items"
  55. tooFewProperties = "%s in %s should have at least %d properties"
  56. tooFewPropertiesNoIn = "%s should have at least %d properties"
  57. tooManyProperties = "%s in %s should have at most %d properties"
  58. tooManyPropertiesNoIn = "%s should have at most %d properties"
  59. unallowedProperty = "%s.%s in %s is a forbidden property"
  60. unallowedPropertyNoIn = "%s.%s is a forbidden property"
  61. failedAllPatternProps = "%s.%s in %s failed all pattern properties"
  62. failedAllPatternPropsNoIn = "%s.%s failed all pattern properties"
  63. multipleOfMustBePositive = "factor MultipleOf declared for %s must be positive: %v"
  64. )
  65. // All code responses can be used to differentiate errors for different handling
  66. // by the consuming program
  67. const (
  68. // CompositeErrorCode remains 422 for backwards-compatibility
  69. // and to separate it from validation errors with cause
  70. CompositeErrorCode = 422
  71. // InvalidTypeCode is used for any subclass of invalid types
  72. InvalidTypeCode = 600 + iota
  73. RequiredFailCode
  74. TooLongFailCode
  75. TooShortFailCode
  76. PatternFailCode
  77. EnumFailCode
  78. MultipleOfFailCode
  79. MaxFailCode
  80. MinFailCode
  81. UniqueFailCode
  82. MaxItemsFailCode
  83. MinItemsFailCode
  84. NoAdditionalItemsCode
  85. TooFewPropertiesCode
  86. TooManyPropertiesCode
  87. UnallowedPropertyCode
  88. FailedAllPatternPropsCode
  89. MultipleOfMustBePositiveCode
  90. )
  91. // CompositeError is an error that groups several errors together
  92. type CompositeError struct {
  93. Errors []error
  94. code int32
  95. message string
  96. }
  97. // Code for this error
  98. func (c *CompositeError) Code() int32 {
  99. return c.code
  100. }
  101. func (c *CompositeError) Error() string {
  102. if len(c.Errors) > 0 {
  103. msgs := []string{c.message + ":"}
  104. for _, e := range c.Errors {
  105. msgs = append(msgs, e.Error())
  106. }
  107. return strings.Join(msgs, "\n")
  108. }
  109. return c.message
  110. }
  111. // CompositeValidationError an error to wrap a bunch of other errors
  112. func CompositeValidationError(errors ...error) *CompositeError {
  113. return &CompositeError{
  114. code: CompositeErrorCode,
  115. Errors: append([]error{}, errors...),
  116. message: "validation failure list",
  117. }
  118. }
  119. // FailedAllPatternProperties an error for when the property doesn't match a pattern
  120. func FailedAllPatternProperties(name, in, key string) *Validation {
  121. msg := fmt.Sprintf(failedAllPatternProps, name, key, in)
  122. if in == "" {
  123. msg = fmt.Sprintf(failedAllPatternPropsNoIn, name, key)
  124. }
  125. return &Validation{
  126. code: FailedAllPatternPropsCode,
  127. Name: name,
  128. In: in,
  129. Value: key,
  130. message: msg,
  131. }
  132. }
  133. // PropertyNotAllowed an error for when the property doesn't match a pattern
  134. func PropertyNotAllowed(name, in, key string) *Validation {
  135. msg := fmt.Sprintf(unallowedProperty, name, key, in)
  136. if in == "" {
  137. msg = fmt.Sprintf(unallowedPropertyNoIn, name, key)
  138. }
  139. return &Validation{
  140. code: UnallowedPropertyCode,
  141. Name: name,
  142. In: in,
  143. Value: key,
  144. message: msg,
  145. }
  146. }
  147. // TooFewProperties an error for an object with too few properties
  148. func TooFewProperties(name, in string, n int64) *Validation {
  149. msg := fmt.Sprintf(tooFewProperties, name, in, n)
  150. if in == "" {
  151. msg = fmt.Sprintf(tooFewPropertiesNoIn, name, n)
  152. }
  153. return &Validation{
  154. code: TooFewPropertiesCode,
  155. Name: name,
  156. In: in,
  157. Value: n,
  158. message: msg,
  159. }
  160. }
  161. // TooManyProperties an error for an object with too many properties
  162. func TooManyProperties(name, in string, n int64) *Validation {
  163. msg := fmt.Sprintf(tooManyProperties, name, in, n)
  164. if in == "" {
  165. msg = fmt.Sprintf(tooManyPropertiesNoIn, name, n)
  166. }
  167. return &Validation{
  168. code: TooManyPropertiesCode,
  169. Name: name,
  170. In: in,
  171. Value: n,
  172. message: msg,
  173. }
  174. }
  175. // AdditionalItemsNotAllowed an error for invalid additional items
  176. func AdditionalItemsNotAllowed(name, in string) *Validation {
  177. msg := fmt.Sprintf(noAdditionalItems, name, in)
  178. if in == "" {
  179. msg = fmt.Sprintf(noAdditionalItemsNoIn, name)
  180. }
  181. return &Validation{
  182. code: NoAdditionalItemsCode,
  183. Name: name,
  184. In: in,
  185. message: msg,
  186. }
  187. }
  188. // InvalidCollectionFormat another flavor of invalid type error
  189. func InvalidCollectionFormat(name, in, format string) *Validation {
  190. return &Validation{
  191. code: InvalidTypeCode,
  192. Name: name,
  193. In: in,
  194. Value: format,
  195. message: fmt.Sprintf("the collection format %q is not supported for the %s param %q", format, in, name),
  196. }
  197. }
  198. // InvalidTypeName an error for when the type is invalid
  199. func InvalidTypeName(typeName string) *Validation {
  200. return &Validation{
  201. code: InvalidTypeCode,
  202. Value: typeName,
  203. message: fmt.Sprintf(invalidType, typeName),
  204. }
  205. }
  206. // InvalidType creates an error for when the type is invalid
  207. func InvalidType(name, in, typeName string, value interface{}) *Validation {
  208. var message string
  209. if in != "" {
  210. switch value.(type) {
  211. case string:
  212. message = fmt.Sprintf(typeFailWithData, name, in, typeName, value)
  213. case error:
  214. message = fmt.Sprintf(typeFailWithError, name, in, typeName, value)
  215. default:
  216. message = fmt.Sprintf(typeFail, name, in, typeName)
  217. }
  218. } else {
  219. switch value.(type) {
  220. case string:
  221. message = fmt.Sprintf(typeFailWithDataNoIn, name, typeName, value)
  222. case error:
  223. message = fmt.Sprintf(typeFailWithErrorNoIn, name, typeName, value)
  224. default:
  225. message = fmt.Sprintf(typeFailNoIn, name, typeName)
  226. }
  227. }
  228. return &Validation{
  229. code: InvalidTypeCode,
  230. Name: name,
  231. In: in,
  232. Value: value,
  233. message: message,
  234. }
  235. }
  236. // DuplicateItems error for when an array contains duplicates
  237. func DuplicateItems(name, in string) *Validation {
  238. msg := fmt.Sprintf(uniqueFail, name, in)
  239. if in == "" {
  240. msg = fmt.Sprintf(uniqueFailNoIn, name)
  241. }
  242. return &Validation{
  243. code: UniqueFailCode,
  244. Name: name,
  245. In: in,
  246. message: msg,
  247. }
  248. }
  249. // TooManyItems error for when an array contains too many items
  250. func TooManyItems(name, in string, max int64) *Validation {
  251. msg := fmt.Sprintf(maxItemsFail, name, in, max)
  252. if in == "" {
  253. msg = fmt.Sprintf(maxItemsFailNoIn, name, max)
  254. }
  255. return &Validation{
  256. code: MaxItemsFailCode,
  257. Name: name,
  258. In: in,
  259. message: msg,
  260. }
  261. }
  262. // TooFewItems error for when an array contains too few items
  263. func TooFewItems(name, in string, min int64) *Validation {
  264. msg := fmt.Sprintf(minItemsFail, name, in, min)
  265. if in == "" {
  266. msg = fmt.Sprintf(minItemsFailNoIn, name, min)
  267. }
  268. return &Validation{
  269. code: MinItemsFailCode,
  270. Name: name,
  271. In: in,
  272. message: msg,
  273. }
  274. }
  275. // ExceedsMaximumInt error for when maxinum validation fails
  276. func ExceedsMaximumInt(name, in string, max int64, exclusive bool) *Validation {
  277. var message string
  278. if in == "" {
  279. m := maxIncFailNoIn
  280. if exclusive {
  281. m = maxExcFailNoIn
  282. }
  283. message = fmt.Sprintf(m, name, max)
  284. } else {
  285. m := maxIncFail
  286. if exclusive {
  287. m = maxExcFail
  288. }
  289. message = fmt.Sprintf(m, name, in, max)
  290. }
  291. return &Validation{
  292. code: MaxFailCode,
  293. Name: name,
  294. In: in,
  295. Value: max,
  296. message: message,
  297. }
  298. }
  299. // ExceedsMaximumUint error for when maxinum validation fails
  300. func ExceedsMaximumUint(name, in string, max uint64, exclusive bool) *Validation {
  301. var message string
  302. if in == "" {
  303. m := maxIncFailNoIn
  304. if exclusive {
  305. m = maxExcFailNoIn
  306. }
  307. message = fmt.Sprintf(m, name, max)
  308. } else {
  309. m := maxIncFail
  310. if exclusive {
  311. m = maxExcFail
  312. }
  313. message = fmt.Sprintf(m, name, in, max)
  314. }
  315. return &Validation{
  316. code: MaxFailCode,
  317. Name: name,
  318. In: in,
  319. Value: max,
  320. message: message,
  321. }
  322. }
  323. // ExceedsMaximum error for when maxinum validation fails
  324. func ExceedsMaximum(name, in string, max float64, exclusive bool) *Validation {
  325. var message string
  326. if in == "" {
  327. m := maxIncFailNoIn
  328. if exclusive {
  329. m = maxExcFailNoIn
  330. }
  331. message = fmt.Sprintf(m, name, max)
  332. } else {
  333. m := maxIncFail
  334. if exclusive {
  335. m = maxExcFail
  336. }
  337. message = fmt.Sprintf(m, name, in, max)
  338. }
  339. return &Validation{
  340. code: MaxFailCode,
  341. Name: name,
  342. In: in,
  343. Value: max,
  344. message: message,
  345. }
  346. }
  347. // ExceedsMinimumInt error for when maxinum validation fails
  348. func ExceedsMinimumInt(name, in string, min int64, exclusive bool) *Validation {
  349. var message string
  350. if in == "" {
  351. m := minIncFailNoIn
  352. if exclusive {
  353. m = minExcFailNoIn
  354. }
  355. message = fmt.Sprintf(m, name, min)
  356. } else {
  357. m := minIncFail
  358. if exclusive {
  359. m = minExcFail
  360. }
  361. message = fmt.Sprintf(m, name, in, min)
  362. }
  363. return &Validation{
  364. code: MinFailCode,
  365. Name: name,
  366. In: in,
  367. Value: min,
  368. message: message,
  369. }
  370. }
  371. // ExceedsMinimumUint error for when maxinum validation fails
  372. func ExceedsMinimumUint(name, in string, min uint64, exclusive bool) *Validation {
  373. var message string
  374. if in == "" {
  375. m := minIncFailNoIn
  376. if exclusive {
  377. m = minExcFailNoIn
  378. }
  379. message = fmt.Sprintf(m, name, min)
  380. } else {
  381. m := minIncFail
  382. if exclusive {
  383. m = minExcFail
  384. }
  385. message = fmt.Sprintf(m, name, in, min)
  386. }
  387. return &Validation{
  388. code: MinFailCode,
  389. Name: name,
  390. In: in,
  391. Value: min,
  392. message: message,
  393. }
  394. }
  395. // ExceedsMinimum error for when maxinum validation fails
  396. func ExceedsMinimum(name, in string, min float64, exclusive bool) *Validation {
  397. var message string
  398. if in == "" {
  399. m := minIncFailNoIn
  400. if exclusive {
  401. m = minExcFailNoIn
  402. }
  403. message = fmt.Sprintf(m, name, min)
  404. } else {
  405. m := minIncFail
  406. if exclusive {
  407. m = minExcFail
  408. }
  409. message = fmt.Sprintf(m, name, in, min)
  410. }
  411. return &Validation{
  412. code: MinFailCode,
  413. Name: name,
  414. In: in,
  415. Value: min,
  416. message: message,
  417. }
  418. }
  419. // NotMultipleOf error for when multiple of validation fails
  420. func NotMultipleOf(name, in string, multiple interface{}) *Validation {
  421. var msg string
  422. if in == "" {
  423. msg = fmt.Sprintf(multipleOfFailNoIn, name, multiple)
  424. } else {
  425. msg = fmt.Sprintf(multipleOfFail, name, in, multiple)
  426. }
  427. return &Validation{
  428. code: MultipleOfFailCode,
  429. Name: name,
  430. In: in,
  431. Value: multiple,
  432. message: msg,
  433. }
  434. }
  435. // EnumFail error for when an enum validation fails
  436. func EnumFail(name, in string, value interface{}, values []interface{}) *Validation {
  437. var msg string
  438. if in == "" {
  439. msg = fmt.Sprintf(enumFailNoIn, name, values)
  440. } else {
  441. msg = fmt.Sprintf(enumFail, name, in, values)
  442. }
  443. return &Validation{
  444. code: EnumFailCode,
  445. Name: name,
  446. In: in,
  447. Value: value,
  448. Values: values,
  449. message: msg,
  450. }
  451. }
  452. // Required error for when a value is missing
  453. func Required(name, in string) *Validation {
  454. var msg string
  455. if in == "" {
  456. msg = fmt.Sprintf(requiredFailNoIn, name)
  457. } else {
  458. msg = fmt.Sprintf(requiredFail, name, in)
  459. }
  460. return &Validation{
  461. code: RequiredFailCode,
  462. Name: name,
  463. In: in,
  464. message: msg,
  465. }
  466. }
  467. // TooLong error for when a string is too long
  468. func TooLong(name, in string, max int64) *Validation {
  469. var msg string
  470. if in == "" {
  471. msg = fmt.Sprintf(tooLongMessageNoIn, name, max)
  472. } else {
  473. msg = fmt.Sprintf(tooLongMessage, name, in, max)
  474. }
  475. return &Validation{
  476. code: TooLongFailCode,
  477. Name: name,
  478. In: in,
  479. message: msg,
  480. }
  481. }
  482. // TooShort error for when a string is too short
  483. func TooShort(name, in string, min int64) *Validation {
  484. var msg string
  485. if in == "" {
  486. msg = fmt.Sprintf(tooShortMessageNoIn, name, min)
  487. } else {
  488. msg = fmt.Sprintf(tooShortMessage, name, in, min)
  489. }
  490. return &Validation{
  491. code: TooShortFailCode,
  492. Name: name,
  493. In: in,
  494. message: msg,
  495. }
  496. }
  497. // FailedPattern error for when a string fails a regex pattern match
  498. // the pattern that is returned is the ECMA syntax version of the pattern not the golang version.
  499. func FailedPattern(name, in, pattern string) *Validation {
  500. var msg string
  501. if in == "" {
  502. msg = fmt.Sprintf(patternFailNoIn, name, pattern)
  503. } else {
  504. msg = fmt.Sprintf(patternFail, name, in, pattern)
  505. }
  506. return &Validation{
  507. code: PatternFailCode,
  508. Name: name,
  509. In: in,
  510. message: msg,
  511. }
  512. }
  513. // MultipleOfMustBePositive error for when a
  514. // multipleOf factor is negative
  515. func MultipleOfMustBePositive(name, in string, factor interface{}) *Validation {
  516. return &Validation{
  517. code: MultipleOfMustBePositiveCode,
  518. Name: name,
  519. In: in,
  520. Value: factor,
  521. message: fmt.Sprintf(multipleOfMustBePositive, name, factor),
  522. }
  523. }