validators.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. // Copyright 2019 Yunion
  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 validators
  15. // TODO
  16. //
  17. // email
  18. // uuid
  19. // uri
  20. import (
  21. "context"
  22. "database/sql"
  23. "math"
  24. "net"
  25. "reflect"
  26. "regexp"
  27. "strconv"
  28. "strings"
  29. "yunion.io/x/jsonutils"
  30. "yunion.io/x/pkg/errors"
  31. "yunion.io/x/pkg/gotypes"
  32. "yunion.io/x/pkg/util/netutils"
  33. "yunion.io/x/pkg/util/regutils"
  34. "yunion.io/x/sqlchemy"
  35. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  36. "yunion.io/x/onecloud/pkg/httperrors"
  37. "yunion.io/x/onecloud/pkg/mcclient"
  38. "yunion.io/x/onecloud/pkg/util/choices"
  39. )
  40. type ValidatorFunc func(context.Context, *jsonutils.JSONDict) error
  41. type IValidatorBase interface {
  42. Validate(ctx context.Context, data *jsonutils.JSONDict) error
  43. }
  44. type IValidator interface {
  45. IValidatorBase
  46. Optional(bool) IValidator
  47. getValue() interface{}
  48. setDefault(data *jsonutils.JSONDict) bool
  49. }
  50. type Validator struct {
  51. parent IValidator
  52. Key string
  53. optional bool
  54. defaultVal interface{}
  55. value jsonutils.JSONObject
  56. }
  57. func (v *Validator) SetParent(parent IValidator) IValidator {
  58. v.parent = parent
  59. return parent
  60. }
  61. func (v *Validator) Optional(optional bool) IValidator {
  62. v.optional = optional
  63. return v.parent
  64. }
  65. func (v *Validator) Default(defaultVal interface{}) IValidator {
  66. v.defaultVal = defaultVal
  67. return v.parent
  68. }
  69. func (v *Validator) getValue() interface{} {
  70. return nil
  71. }
  72. func (v *Validator) setDefault(data *jsonutils.JSONDict) bool {
  73. switch v.defaultVal.(type) {
  74. case string:
  75. s := v.defaultVal.(string)
  76. v.value = jsonutils.NewString(s)
  77. data.Set(v.Key, v.value)
  78. return true
  79. case bool:
  80. b := v.defaultVal.(bool)
  81. v.value = jsonutils.NewBool(b)
  82. data.Set(v.Key, v.value)
  83. return true
  84. case int, int32, int64, uint, uint32, uint64:
  85. value := reflect.ValueOf(v.defaultVal)
  86. value64 := value.Convert(gotypes.Int64Type)
  87. defaultVal64 := value64.Interface().(int64)
  88. v.value = jsonutils.NewInt(defaultVal64)
  89. data.Set(v.Key, v.value)
  90. return true
  91. }
  92. return false
  93. }
  94. func (v *Validator) Validate(data *jsonutils.JSONDict) error {
  95. err, _ := v.validateEx(data)
  96. return err
  97. }
  98. func (v *Validator) validateEx(data *jsonutils.JSONDict) (err error, isSet bool) {
  99. if !data.Contains(v.Key) {
  100. if v.defaultVal != nil {
  101. isSet = v.parent.setDefault(data)
  102. return nil, isSet
  103. }
  104. if !v.optional {
  105. err = newMissingKeyError(v.Key)
  106. return
  107. }
  108. return
  109. }
  110. value, err := data.Get(v.Key)
  111. if err != nil {
  112. return
  113. }
  114. v.value = value
  115. isSet = true
  116. return
  117. }
  118. type ValidatorIPv4Prefix struct {
  119. Validator
  120. Value netutils.IPV4Prefix
  121. }
  122. func NewIPv4PrefixValidator(key string) *ValidatorIPv4Prefix {
  123. v := &ValidatorIPv4Prefix{
  124. Validator: Validator{Key: key},
  125. }
  126. v.SetParent(v)
  127. return v
  128. }
  129. func (v *ValidatorIPv4Prefix) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  130. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  131. return err
  132. }
  133. s, err := v.value.GetString()
  134. if err != nil {
  135. return newGeneralError(v.Key, err)
  136. }
  137. v.Value, err = netutils.NewIPV4Prefix(s)
  138. if err != nil {
  139. return err
  140. }
  141. data.Set(v.Key, jsonutils.NewString(s))
  142. return nil
  143. }
  144. type ValidatorIntChoices struct {
  145. Validator
  146. choices []int64
  147. Value int64
  148. }
  149. func NewIntChoicesValidator(key string, choices []int64) *ValidatorIntChoices {
  150. v := &ValidatorIntChoices{
  151. Validator: Validator{Key: key},
  152. choices: choices,
  153. }
  154. v.SetParent(v)
  155. return v
  156. }
  157. func (v *ValidatorIntChoices) has(i int64) bool {
  158. for _, c := range v.choices {
  159. if c == i {
  160. return true
  161. }
  162. }
  163. return false
  164. }
  165. func (v *ValidatorIntChoices) Default(i int64) IValidator {
  166. if v.has(i) {
  167. v.Validator.Default(i)
  168. return v
  169. }
  170. panic("invalid default for " + v.Key)
  171. }
  172. func (v *ValidatorIntChoices) getValue() interface{} {
  173. return v.Value
  174. }
  175. func (v *ValidatorIntChoices) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  176. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  177. return err
  178. }
  179. i, err := v.value.Int()
  180. if err != nil {
  181. return newGeneralError(v.Key, err)
  182. }
  183. if !v.has(i) {
  184. return newInvalidIntChoiceError(v.Key, v.choices, i)
  185. }
  186. // in case it's stringified from v.value
  187. data.Set(v.Key, jsonutils.NewInt(i))
  188. v.Value = i
  189. return nil
  190. }
  191. type ValidatorStringChoices struct {
  192. Validator
  193. Choices choices.Choices
  194. Value string
  195. }
  196. func NewStringChoicesValidator(key string, choices choices.Choices) *ValidatorStringChoices {
  197. v := &ValidatorStringChoices{
  198. Validator: Validator{Key: key},
  199. Choices: choices,
  200. }
  201. v.SetParent(v)
  202. return v
  203. }
  204. func (v *ValidatorStringChoices) Default(s string) IValidator {
  205. if v.Choices.Has(s) {
  206. v.Validator.Default(s)
  207. return v
  208. }
  209. panic("invalid default for " + v.Key)
  210. }
  211. func (v *ValidatorStringChoices) getValue() interface{} {
  212. return v.Value
  213. }
  214. func (v *ValidatorStringChoices) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  215. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  216. return err
  217. }
  218. s, err := v.value.GetString()
  219. if err != nil {
  220. return newGeneralError(v.Key, err)
  221. }
  222. if !v.Choices.Has(s) {
  223. return newInvalidChoiceError(v.Key, v.Choices, s)
  224. }
  225. // in case it's stringified from v.value
  226. data.Set(v.Key, jsonutils.NewString(s))
  227. v.Value = s
  228. return nil
  229. }
  230. type ValidatorStringMultiChoices struct {
  231. Validator
  232. Choices choices.Choices
  233. Value string
  234. sep string
  235. keepDup bool
  236. }
  237. func NewStringMultiChoicesValidator(key string, choices choices.Choices) *ValidatorStringMultiChoices {
  238. v := &ValidatorStringMultiChoices{
  239. Validator: Validator{Key: key},
  240. Choices: choices,
  241. }
  242. v.SetParent(v)
  243. return v
  244. }
  245. func (v *ValidatorStringMultiChoices) Sep(s string) *ValidatorStringMultiChoices {
  246. v.sep = s
  247. return v
  248. }
  249. func (v *ValidatorStringMultiChoices) KeepDup(b bool) *ValidatorStringMultiChoices {
  250. v.keepDup = b
  251. return v
  252. }
  253. func (v *ValidatorStringMultiChoices) validateString(s string) (string, bool) {
  254. choices := strings.Split(s, v.sep)
  255. j := 0
  256. for i, choice := range choices {
  257. if !v.Choices.Has(choice) {
  258. return "", false
  259. }
  260. if !v.keepDup {
  261. isDup := false
  262. for k := 0; k < j; k++ {
  263. if choices[k] == choices[i] {
  264. isDup = true
  265. }
  266. }
  267. if !isDup {
  268. choices[j] = choices[i]
  269. j += 1
  270. }
  271. }
  272. }
  273. if !v.keepDup {
  274. choices = choices[:j]
  275. }
  276. s = strings.Join(choices, v.sep)
  277. return s, true
  278. }
  279. func (v *ValidatorStringMultiChoices) Default(s string) IValidator {
  280. s, ok := v.validateString(s)
  281. if !ok {
  282. panic("invalid default for " + v.Key)
  283. }
  284. v.Validator.Default(s)
  285. return v
  286. }
  287. func (v *ValidatorStringMultiChoices) getValue() interface{} {
  288. return v.Value
  289. }
  290. func (v *ValidatorStringMultiChoices) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  291. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  292. return err
  293. }
  294. s, err := v.value.GetString()
  295. if err != nil {
  296. return newGeneralError(v.Key, err)
  297. }
  298. s, ok := v.validateString(s)
  299. if !ok {
  300. return newInvalidChoiceError(v.Key, v.Choices, s)
  301. }
  302. // in case it's stringified from v.value
  303. data.Set(v.Key, jsonutils.NewString(s))
  304. v.Value = s
  305. return nil
  306. }
  307. type ValidatorBool struct {
  308. Validator
  309. Value bool
  310. }
  311. func (v *ValidatorBool) getValue() interface{} {
  312. return v.Value
  313. }
  314. func (v *ValidatorBool) Default(i bool) IValidator {
  315. return v.Validator.Default(i)
  316. }
  317. func (v *ValidatorBool) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  318. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  319. return err
  320. }
  321. i, err := v.value.Bool()
  322. if err != nil {
  323. return newInvalidTypeError(v.Key, "bool", err)
  324. }
  325. data.Set(v.Key, jsonutils.NewBool(i))
  326. v.Value = i
  327. return nil
  328. }
  329. func NewBoolValidator(key string) *ValidatorBool {
  330. v := &ValidatorBool{
  331. Validator: Validator{Key: key},
  332. }
  333. v.SetParent(v)
  334. return v
  335. }
  336. type ValidatorRange struct {
  337. Validator
  338. Lower int64
  339. Upper int64
  340. Value int64
  341. }
  342. func (v *ValidatorRange) getValue() interface{} {
  343. return v.Value
  344. }
  345. func (v *ValidatorRange) Default(i int64) IValidator {
  346. if i >= v.Lower && i <= v.Upper {
  347. return v.Validator.Default(i)
  348. }
  349. panic("invalid default for " + v.Key)
  350. }
  351. func (v *ValidatorRange) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  352. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  353. return err
  354. }
  355. i, err := v.value.Int()
  356. if err != nil {
  357. return newInvalidTypeError(v.Key, "integer", err)
  358. }
  359. if i < v.Lower || i > v.Upper {
  360. return newNotInRangeError(v.Key, i, v.Lower, v.Upper)
  361. }
  362. data.Set(v.Key, jsonutils.NewInt(i))
  363. v.Value = i
  364. return nil
  365. }
  366. func NewRangeValidator(key string, lower int64, upper int64) *ValidatorRange {
  367. v := &ValidatorRange{
  368. Validator: Validator{Key: key},
  369. Lower: lower,
  370. Upper: upper,
  371. }
  372. v.SetParent(v)
  373. return v
  374. }
  375. func NewPortValidator(key string) *ValidatorRange {
  376. return NewRangeValidator(key, 1, 65535)
  377. }
  378. func NewVlanIdValidator(key string) *ValidatorRange {
  379. // The convention is vendor specific
  380. //
  381. // 0, 4095: reserved
  382. // 1: no vlan tagging
  383. return NewRangeValidator(key, 1, 4094)
  384. }
  385. func NewNonNegativeValidator(key string) *ValidatorRange {
  386. return NewRangeValidator(key, 0, math.MaxInt64)
  387. }
  388. type ValidatorModelIdOrName struct {
  389. Validator
  390. ModelKeyword string
  391. OwnerId mcclient.IIdentityProvider
  392. ModelManager db.IModelManager
  393. Model db.IModel
  394. modelIdKey string
  395. noPendingDeleted bool
  396. allowEmpty bool
  397. }
  398. func (v *ValidatorModelIdOrName) GetProjectId() string {
  399. return v.OwnerId.GetProjectId()
  400. }
  401. func (v *ValidatorModelIdOrName) GetUserId() string {
  402. return v.OwnerId.GetUserId()
  403. }
  404. func (v *ValidatorModelIdOrName) GetTenantId() string {
  405. return v.OwnerId.GetTenantId()
  406. }
  407. func (v *ValidatorModelIdOrName) GetProjectDomainId() string {
  408. return v.OwnerId.GetProjectDomainId()
  409. }
  410. func (v *ValidatorModelIdOrName) GetUserName() string {
  411. return v.OwnerId.GetUserName()
  412. }
  413. func (v *ValidatorModelIdOrName) GetProjectName() string {
  414. return v.OwnerId.GetProjectName()
  415. }
  416. func (v *ValidatorModelIdOrName) GetTenantName() string {
  417. return v.OwnerId.GetTenantName()
  418. }
  419. func (v *ValidatorModelIdOrName) GetProjectDomain() string {
  420. return v.OwnerId.GetProjectDomain()
  421. }
  422. func (v *ValidatorModelIdOrName) GetDomainId() string {
  423. return v.OwnerId.GetDomainId()
  424. }
  425. func (v *ValidatorModelIdOrName) GetDomainName() string {
  426. return v.OwnerId.GetDomainName()
  427. }
  428. func (v *ValidatorModelIdOrName) getValue() interface{} {
  429. return v.Model
  430. }
  431. func NewModelIdOrNameValidator(key string, modelKeyword string, ownerId mcclient.IIdentityProvider) *ValidatorModelIdOrName {
  432. v := &ValidatorModelIdOrName{
  433. Validator: Validator{Key: key},
  434. OwnerId: ownerId,
  435. ModelKeyword: modelKeyword,
  436. modelIdKey: key + "_id",
  437. noPendingDeleted: true,
  438. }
  439. v.SetParent(v)
  440. return v
  441. }
  442. func (v *ValidatorModelIdOrName) ModelIdKey(modelIdKey string) *ValidatorModelIdOrName {
  443. v.modelIdKey = modelIdKey
  444. return v
  445. }
  446. // AllowPendingDeleted allows the to-be-validated id or name to be of a pending deleted model
  447. func (v *ValidatorModelIdOrName) AllowPendingDeleted(b bool) *ValidatorModelIdOrName {
  448. v.noPendingDeleted = !b
  449. return v
  450. }
  451. func (v *ValidatorModelIdOrName) AllowEmpty(b bool) *ValidatorModelIdOrName {
  452. v.allowEmpty = b
  453. return v
  454. }
  455. func (v *ValidatorModelIdOrName) validate(ctx context.Context, data *jsonutils.JSONDict) error {
  456. if !data.Contains(v.Key) && data.Contains(v.modelIdKey) {
  457. // a hack when validator is used solely for fetching model
  458. // object. This can happen when input json data was validated
  459. // more than once in different places
  460. j, err := data.Get(v.modelIdKey)
  461. if err != nil {
  462. return err
  463. }
  464. data.Set(v.Key, j)
  465. defer func() {
  466. // restore
  467. data.Remove(v.Key)
  468. }()
  469. }
  470. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  471. return err
  472. }
  473. modelIdOrName, err := v.value.GetString()
  474. if err != nil {
  475. return err
  476. }
  477. if modelIdOrName == "" && v.allowEmpty {
  478. return nil
  479. }
  480. modelManager := db.GetModelManager(v.ModelKeyword)
  481. if modelManager == nil {
  482. return newModelManagerError(v.ModelKeyword)
  483. }
  484. v.ModelManager = modelManager
  485. model, err := modelManager.FetchByIdOrName(ctx, v, modelIdOrName)
  486. if err != nil {
  487. if err == sql.ErrNoRows {
  488. return newModelNotFoundError(v.ModelKeyword, modelIdOrName, err)
  489. } else {
  490. return httperrors.NewGeneralError(err)
  491. }
  492. }
  493. if v.noPendingDeleted {
  494. if pd, ok := model.(db.IPendingDeletable); ok && pd.GetPendingDeleted() {
  495. return newModelNotFoundError(v.ModelKeyword, modelIdOrName, nil)
  496. }
  497. }
  498. v.Model = model
  499. return nil
  500. }
  501. func (v *ValidatorModelIdOrName) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  502. err := v.validate(ctx, data)
  503. if err != nil {
  504. return err
  505. }
  506. var val string
  507. if v.Model != nil {
  508. val = v.Model.GetId()
  509. }
  510. if v.modelIdKey != "" {
  511. if data.Contains(v.Key) {
  512. data.Remove(v.Key)
  513. }
  514. if val != "" {
  515. data.Set(v.modelIdKey, jsonutils.NewString(val))
  516. }
  517. }
  518. return nil
  519. }
  520. func (v *ValidatorModelIdOrName) QueryFilter(ctx context.Context, q *sqlchemy.SQuery, data *jsonutils.JSONDict) (*sqlchemy.SQuery, error) {
  521. err := v.validate(ctx, data)
  522. if err != nil {
  523. if IsModelNotFoundError(err) {
  524. // hack
  525. q = q.Equals(v.modelIdKey, "0")
  526. q = q.Equals(v.modelIdKey, "1")
  527. return q, nil
  528. }
  529. return nil, err
  530. }
  531. if v.Model != nil {
  532. q = q.Equals(v.modelIdKey, v.Model.GetId())
  533. }
  534. return q, nil
  535. }
  536. type ValidatorRegexp struct {
  537. Validator
  538. Regexp *regexp.Regexp
  539. Value string
  540. allowEmpty bool
  541. }
  542. func (v *ValidatorRegexp) AllowEmpty(allowEmpty bool) *ValidatorRegexp {
  543. v.allowEmpty = allowEmpty
  544. return v
  545. }
  546. func (v *ValidatorRegexp) getValue() interface{} {
  547. return v.Value
  548. }
  549. func (v *ValidatorRegexp) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  550. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  551. return err
  552. }
  553. value, err := v.value.GetString()
  554. if err != nil {
  555. return newInvalidTypeError(v.Key, "string", err)
  556. }
  557. if v.allowEmpty && len(value) == 0 {
  558. return nil
  559. }
  560. if !v.Regexp.MatchString(value) {
  561. return newInvalidValueError(v.Key, value)
  562. }
  563. v.Value = value
  564. return nil
  565. }
  566. func NewRegexpValidator(key string, regexp *regexp.Regexp) *ValidatorRegexp {
  567. v := &ValidatorRegexp{
  568. Validator: Validator{Key: key},
  569. Regexp: regexp,
  570. }
  571. v.SetParent(v)
  572. return v
  573. }
  574. type ValidatorDomainName struct {
  575. ValidatorRegexp
  576. }
  577. func NewDomainNameValidator(key string) *ValidatorDomainName {
  578. v := &ValidatorDomainName{
  579. ValidatorRegexp: *NewRegexpValidator(key, regutils.DOMAINNAME_REG),
  580. }
  581. v.SetParent(v)
  582. return v
  583. }
  584. type ValidatorHostPort struct {
  585. ValidatorRegexp
  586. optionalPort bool
  587. Domain string
  588. Port int
  589. Value string
  590. }
  591. var regHostPort *regexp.Regexp
  592. func init() {
  593. // guard against surprise
  594. exp := regutils.DOMAINNAME_REG.String()
  595. if exp != "" && exp[len(exp)-1] == '$' {
  596. exp = exp[:len(exp)-1]
  597. }
  598. exp += "(?::[0-9]{1,5})?"
  599. regHostPort = regexp.MustCompile(exp)
  600. }
  601. func NewHostPortValidator(key string) *ValidatorHostPort {
  602. v := &ValidatorHostPort{
  603. ValidatorRegexp: *NewRegexpValidator(key, regHostPort),
  604. }
  605. v.SetParent(v)
  606. return v
  607. }
  608. func (v *ValidatorHostPort) getValue() interface{} {
  609. return v.Value
  610. }
  611. func (v *ValidatorHostPort) OptionalPort(optionalPort bool) *ValidatorHostPort {
  612. v.optionalPort = optionalPort
  613. return v
  614. }
  615. func (v *ValidatorHostPort) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  616. err := v.ValidatorRegexp.Validate(ctx, data)
  617. if err != nil {
  618. return err
  619. }
  620. hostPort := v.ValidatorRegexp.Value
  621. if hostPort == "" && (v.optional || v.allowEmpty) {
  622. return nil
  623. }
  624. i := strings.IndexRune(hostPort, ':')
  625. if i < 0 {
  626. if v.optionalPort {
  627. v.Value = hostPort
  628. v.Domain = hostPort
  629. return nil
  630. }
  631. return newInvalidValueError(v.Key, "port missing")
  632. }
  633. portStr := hostPort[i+1:]
  634. port, err := strconv.ParseUint(portStr, 10, 16)
  635. if err != nil {
  636. return newInvalidValueError(v.Key, "bad port integer: "+err.Error())
  637. }
  638. if port <= 0 {
  639. return newInvalidValueError(v.Key, "negative port")
  640. }
  641. v.Value = hostPort
  642. v.Domain = hostPort[:i]
  643. v.Port = int(port)
  644. return nil
  645. }
  646. type ValidatorURLPath struct {
  647. ValidatorRegexp
  648. }
  649. // URI Path as defined in https://tools.ietf.org/html/rfc3986#section-3.3
  650. var regexpURLPath = regexp.MustCompile(`^(?:/[a-zA-Z0-9.%$&'()*+,;=!~_-]*)*$`)
  651. func NewURLPathValidator(key string) *ValidatorURLPath {
  652. v := &ValidatorURLPath{
  653. ValidatorRegexp: *NewRegexpValidator(key, regexpURLPath),
  654. }
  655. v.SetParent(v)
  656. return v
  657. }
  658. type ValidatorStruct struct {
  659. Validator
  660. Value interface{}
  661. }
  662. func (v *ValidatorStruct) getValue() interface{} {
  663. return v.Value
  664. }
  665. func (v *ValidatorStruct) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  666. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  667. return err
  668. }
  669. err := v.value.Unmarshal(v.Value)
  670. if err != nil {
  671. return newGeneralError(v.Key, err)
  672. }
  673. if valueValidator, ok := v.Value.(IValidatorBase); ok {
  674. err = valueValidator.Validate(ctx, data)
  675. if err != nil {
  676. return newInvalidStructError(v.Key, err)
  677. }
  678. }
  679. data.Set(v.Key, jsonutils.Marshal(v.Value))
  680. return nil
  681. }
  682. func NewStructValidator(key string, value interface{}) *ValidatorStruct {
  683. v := &ValidatorStruct{
  684. Validator: Validator{Key: key},
  685. Value: value,
  686. }
  687. v.SetParent(v)
  688. return v
  689. }
  690. type ValidatorIPv4Addr struct {
  691. Validator
  692. IP net.IP
  693. }
  694. func (v *ValidatorIPv4Addr) getValue() interface{} {
  695. return v.IP
  696. }
  697. func (v *ValidatorIPv4Addr) setDefault(data *jsonutils.JSONDict) bool {
  698. if v.defaultVal == nil {
  699. return false
  700. }
  701. defaultIP, ok := v.defaultVal.(net.IP)
  702. if !ok {
  703. return false
  704. }
  705. value := jsonutils.NewString(defaultIP.String())
  706. v.value = value
  707. data.Set(v.Key, value)
  708. return true
  709. }
  710. func (v *ValidatorIPv4Addr) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  711. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  712. return err
  713. }
  714. s, err := v.value.GetString()
  715. if err != nil {
  716. return newInvalidTypeError(v.Key, "string", err)
  717. }
  718. ip := net.ParseIP(s).To4()
  719. if ip == nil {
  720. return newInvalidValueError(v.Key, s)
  721. }
  722. v.IP = ip
  723. return nil
  724. }
  725. func NewIPv4AddrValidator(key string) *ValidatorIPv4Addr {
  726. v := &ValidatorIPv4Addr{
  727. Validator: Validator{Key: key},
  728. }
  729. v.SetParent(v)
  730. return v
  731. }
  732. var ValidateModel = func(ctx context.Context, userCred mcclient.TokenCredential, manager db.IStandaloneModelManager, id *string) (db.IModel, error) {
  733. if len(*id) == 0 {
  734. return nil, httperrors.NewMissingParameterError(manager.Keyword() + "_id")
  735. }
  736. model, err := manager.FetchByIdOrName(ctx, userCred, *id)
  737. if err != nil {
  738. if errors.Cause(err) == sql.ErrNoRows {
  739. return nil, httperrors.NewResourceNotFoundError2(manager.Keyword(), *id)
  740. }
  741. if errors.Cause(err) == sqlchemy.ErrDuplicateEntry {
  742. return nil, httperrors.NewDuplicateResourceError(manager.Keyword(), *id)
  743. }
  744. return nil, httperrors.NewGeneralError(err)
  745. }
  746. *id = model.GetId()
  747. return model, nil
  748. }