engine_types.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. package validator
  2. import (
  3. "fmt"
  4. "google.golang.org/protobuf/reflect/protoreflect"
  5. validate "git.ikuban.com/server/kubanapis/kuban/api/validate"
  6. )
  7. // validateInt32 验证 int32
  8. func (e *Engine) validateInt32(
  9. vctx *ValidationContext,
  10. fieldRules *validate.FieldRules,
  11. rules *validate.Int32Rules,
  12. value int32,
  13. fieldPath string,
  14. errors *ValidationErrors,
  15. ) error {
  16. if rules.Const != nil && value != *rules.Const {
  17. defaultMsg := fmt.Sprintf("字段 %s 必须等于 %d", fieldPath, *rules.Const)
  18. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  19. e.getErrorMessage(fieldRules, vctx, "const", defaultMsg)))
  20. }
  21. if rules.Lt != nil && value >= *rules.Lt {
  22. defaultMsg := fmt.Sprintf("字段 %s 必须小于 %d", fieldPath, *rules.Lt)
  23. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  24. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  25. }
  26. if rules.Lte != nil && value > *rules.Lte {
  27. defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %d", fieldPath, *rules.Lte)
  28. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  29. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  30. }
  31. if rules.Gt != nil && value <= *rules.Gt {
  32. defaultMsg := fmt.Sprintf("字段 %s 必须大于 %d", fieldPath, *rules.Gt)
  33. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  34. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  35. }
  36. if rules.Gte != nil && value < *rules.Gte {
  37. defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %d", fieldPath, *rules.Gte)
  38. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  39. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  40. }
  41. return e.validateInt32In(value, rules, fieldPath, errors, fieldRules, vctx)
  42. }
  43. func (e *Engine) validateInt32In(value int32, rules *validate.Int32Rules, fieldPath string, errors *ValidationErrors, fieldRules *validate.FieldRules, vctx *ValidationContext) error {
  44. if len(rules.In) > 0 {
  45. found := false
  46. for _, v := range rules.In {
  47. if value == v {
  48. found = true
  49. break
  50. }
  51. }
  52. if !found {
  53. defaultMsg := fmt.Sprintf("字段 %s 的值不在允许的列表中", fieldPath)
  54. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  55. e.getErrorMessage(fieldRules, vctx, "in", defaultMsg)))
  56. }
  57. }
  58. if len(rules.NotIn) > 0 {
  59. for _, v := range rules.NotIn {
  60. if value == v {
  61. defaultMsg := fmt.Sprintf("字段 %s 的值在禁止列表中", fieldPath)
  62. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  63. e.getErrorMessage(fieldRules, vctx, "not_in", defaultMsg)))
  64. break
  65. }
  66. }
  67. }
  68. return nil
  69. }
  70. // validateInt64 验证 int64
  71. func (e *Engine) validateInt64(
  72. vctx *ValidationContext,
  73. fieldRules *validate.FieldRules,
  74. rules *validate.Int64Rules,
  75. value int64,
  76. fieldPath string,
  77. errors *ValidationErrors,
  78. ) error {
  79. if rules.Const != nil && value != *rules.Const {
  80. defaultMsg := fmt.Sprintf("字段 %s 必须等于 %d", fieldPath, *rules.Const)
  81. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  82. e.getErrorMessage(fieldRules, vctx, "const", defaultMsg)))
  83. }
  84. if rules.Lt != nil && value >= *rules.Lt {
  85. defaultMsg := fmt.Sprintf("字段 %s 必须小于 %d", fieldPath, *rules.Lt)
  86. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  87. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  88. }
  89. if rules.Lte != nil && value > *rules.Lte {
  90. defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %d", fieldPath, *rules.Lte)
  91. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  92. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  93. }
  94. if rules.Gt != nil && value <= *rules.Gt {
  95. defaultMsg := fmt.Sprintf("字段 %s 必须大于 %d", fieldPath, *rules.Gt)
  96. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  97. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  98. }
  99. if rules.Gte != nil && value < *rules.Gte {
  100. defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %d", fieldPath, *rules.Gte)
  101. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  102. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  103. }
  104. return e.validateInt64In(value, rules, fieldPath, errors, fieldRules, vctx)
  105. }
  106. func (e *Engine) validateInt64In(value int64, rules *validate.Int64Rules, fieldPath string, errors *ValidationErrors, fieldRules *validate.FieldRules, vctx *ValidationContext) error {
  107. if len(rules.In) > 0 {
  108. found := false
  109. for _, v := range rules.In {
  110. if value == v {
  111. found = true
  112. break
  113. }
  114. }
  115. if !found {
  116. defaultMsg := fmt.Sprintf("字段 %s 的值不在允许的列表中", fieldPath)
  117. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  118. e.getErrorMessage(fieldRules, vctx, "in", defaultMsg)))
  119. }
  120. }
  121. if len(rules.NotIn) > 0 {
  122. for _, v := range rules.NotIn {
  123. if value == v {
  124. defaultMsg := fmt.Sprintf("字段 %s 的值在禁止列表中", fieldPath)
  125. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  126. e.getErrorMessage(fieldRules, vctx, "not_in", defaultMsg)))
  127. break
  128. }
  129. }
  130. }
  131. return nil
  132. }
  133. // validateUInt32 验证 uint32
  134. func (e *Engine) validateUInt32(
  135. vctx *ValidationContext,
  136. fieldRules *validate.FieldRules,
  137. rules *validate.UInt32Rules,
  138. value uint32,
  139. fieldPath string,
  140. errors *ValidationErrors,
  141. ) error {
  142. if rules.Const != nil && value != *rules.Const {
  143. defaultMsg := fmt.Sprintf("字段 %s 必须等于 %d", fieldPath, *rules.Const)
  144. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  145. e.getErrorMessage(fieldRules, vctx, "const", defaultMsg)))
  146. }
  147. if rules.Lt != nil && value >= *rules.Lt {
  148. defaultMsg := fmt.Sprintf("字段 %s 必须小于 %d", fieldPath, *rules.Lt)
  149. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  150. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  151. }
  152. if rules.Lte != nil && value > *rules.Lte {
  153. defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %d", fieldPath, *rules.Lte)
  154. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  155. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  156. }
  157. if rules.Gt != nil && value <= *rules.Gt {
  158. defaultMsg := fmt.Sprintf("字段 %s 必须大于 %d", fieldPath, *rules.Gt)
  159. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  160. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  161. }
  162. if rules.Gte != nil && value < *rules.Gte {
  163. defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %d", fieldPath, *rules.Gte)
  164. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  165. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  166. }
  167. return e.validateUInt32In(value, rules, fieldPath, errors, fieldRules, vctx)
  168. }
  169. func (e *Engine) validateUInt32In(value uint32, rules *validate.UInt32Rules, fieldPath string, errors *ValidationErrors, fieldRules *validate.FieldRules, vctx *ValidationContext) error {
  170. if len(rules.In) > 0 {
  171. found := false
  172. for _, v := range rules.In {
  173. if value == v {
  174. found = true
  175. break
  176. }
  177. }
  178. if !found {
  179. defaultMsg := fmt.Sprintf("字段 %s 的值不在允许的列表中", fieldPath)
  180. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  181. e.getErrorMessage(fieldRules, vctx, "in", defaultMsg)))
  182. }
  183. }
  184. if len(rules.NotIn) > 0 {
  185. for _, v := range rules.NotIn {
  186. if value == v {
  187. defaultMsg := fmt.Sprintf("字段 %s 的值在禁止列表中", fieldPath)
  188. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  189. e.getErrorMessage(fieldRules, vctx, "not_in", defaultMsg)))
  190. break
  191. }
  192. }
  193. }
  194. return nil
  195. }
  196. // validateUInt64 验证 uint64
  197. func (e *Engine) validateUInt64(
  198. vctx *ValidationContext,
  199. fieldRules *validate.FieldRules,
  200. rules *validate.UInt64Rules,
  201. value uint64,
  202. fieldPath string,
  203. errors *ValidationErrors,
  204. ) error {
  205. if rules.Const != nil && value != *rules.Const {
  206. defaultMsg := fmt.Sprintf("字段 %s 必须等于 %d", fieldPath, *rules.Const)
  207. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  208. e.getErrorMessage(fieldRules, vctx, "const", defaultMsg)))
  209. }
  210. if rules.Lt != nil && value >= *rules.Lt {
  211. defaultMsg := fmt.Sprintf("字段 %s 必须小于 %d", fieldPath, *rules.Lt)
  212. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  213. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  214. }
  215. if rules.Lte != nil && value > *rules.Lte {
  216. defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %d", fieldPath, *rules.Lte)
  217. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  218. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  219. }
  220. if rules.Gt != nil && value <= *rules.Gt {
  221. defaultMsg := fmt.Sprintf("字段 %s 必须大于 %d", fieldPath, *rules.Gt)
  222. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  223. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  224. }
  225. if rules.Gte != nil && value < *rules.Gte {
  226. defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %d", fieldPath, *rules.Gte)
  227. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  228. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  229. }
  230. return e.validateUInt64In(value, rules, fieldPath, errors, fieldRules, vctx)
  231. }
  232. func (e *Engine) validateUInt64In(value uint64, rules *validate.UInt64Rules, fieldPath string, errors *ValidationErrors, fieldRules *validate.FieldRules, vctx *ValidationContext) error {
  233. if len(rules.In) > 0 {
  234. found := false
  235. for _, v := range rules.In {
  236. if value == v {
  237. found = true
  238. break
  239. }
  240. }
  241. if !found {
  242. defaultMsg := fmt.Sprintf("字段 %s 的值不在允许的列表中", fieldPath)
  243. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  244. e.getErrorMessage(fieldRules, vctx, "in", defaultMsg)))
  245. }
  246. }
  247. if len(rules.NotIn) > 0 {
  248. for _, v := range rules.NotIn {
  249. if value == v {
  250. defaultMsg := fmt.Sprintf("字段 %s 的值在禁止列表中", fieldPath)
  251. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  252. e.getErrorMessage(fieldRules, vctx, "not_in", defaultMsg)))
  253. break
  254. }
  255. }
  256. }
  257. return nil
  258. }
  259. // validateFloat 验证 float32
  260. func (e *Engine) validateFloat(
  261. vctx *ValidationContext,
  262. fieldRules *validate.FieldRules,
  263. rules *validate.FloatRules,
  264. value float32,
  265. fieldPath string,
  266. errors *ValidationErrors,
  267. ) error {
  268. if rules.Const != nil && value != *rules.Const {
  269. defaultMsg := fmt.Sprintf("字段 %s 必须等于 %f", fieldPath, *rules.Const)
  270. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  271. e.getErrorMessage(fieldRules, vctx, "const", defaultMsg)))
  272. }
  273. if rules.Lt != nil && value >= *rules.Lt {
  274. defaultMsg := fmt.Sprintf("字段 %s 必须小于 %f", fieldPath, *rules.Lt)
  275. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  276. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  277. }
  278. if rules.Lte != nil && value > *rules.Lte {
  279. defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %f", fieldPath, *rules.Lte)
  280. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  281. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  282. }
  283. if rules.Gt != nil && value <= *rules.Gt {
  284. defaultMsg := fmt.Sprintf("字段 %s 必须大于 %f", fieldPath, *rules.Gt)
  285. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  286. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  287. }
  288. if rules.Gte != nil && value < *rules.Gte {
  289. defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %f", fieldPath, *rules.Gte)
  290. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  291. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  292. }
  293. return nil
  294. }
  295. // validateDouble 验证 float64
  296. func (e *Engine) validateDouble(
  297. vctx *ValidationContext,
  298. fieldRules *validate.FieldRules,
  299. rules *validate.DoubleRules,
  300. value float64,
  301. fieldPath string,
  302. errors *ValidationErrors,
  303. ) error {
  304. if rules.Const != nil && value != *rules.Const {
  305. defaultMsg := fmt.Sprintf("字段 %s 必须等于 %f", fieldPath, *rules.Const)
  306. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  307. e.getErrorMessage(fieldRules, vctx, "const", defaultMsg)))
  308. }
  309. if rules.Lt != nil && value >= *rules.Lt {
  310. defaultMsg := fmt.Sprintf("字段 %s 必须小于 %f", fieldPath, *rules.Lt)
  311. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  312. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  313. }
  314. if rules.Lte != nil && value > *rules.Lte {
  315. defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %f", fieldPath, *rules.Lte)
  316. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  317. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  318. }
  319. if rules.Gt != nil && value <= *rules.Gt {
  320. defaultMsg := fmt.Sprintf("字段 %s 必须大于 %f", fieldPath, *rules.Gt)
  321. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  322. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  323. }
  324. if rules.Gte != nil && value < *rules.Gte {
  325. defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %f", fieldPath, *rules.Gte)
  326. errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange,
  327. e.getErrorMessage(fieldRules, vctx, "range", defaultMsg)))
  328. }
  329. return nil
  330. }
  331. // validateBool 验证 bool
  332. func (e *Engine) validateBool(
  333. vctx *ValidationContext,
  334. fieldRules *validate.FieldRules,
  335. rules *validate.BoolRules,
  336. value bool,
  337. fieldPath string,
  338. errors *ValidationErrors,
  339. ) error {
  340. if rules.Const != nil && value != *rules.Const {
  341. defaultMsg := fmt.Sprintf("字段 %s 必须等于 %t", fieldPath, *rules.Const)
  342. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  343. e.getErrorMessage(fieldRules, vctx, "const", defaultMsg)))
  344. }
  345. return nil
  346. }
  347. // validateRepeated 验证 repeated 字段
  348. func (e *Engine) validateRepeated(
  349. vctx *ValidationContext,
  350. fieldRules *validate.FieldRules,
  351. rules *validate.RepeatedRules,
  352. list protoreflect.List,
  353. field protoreflect.FieldDescriptor,
  354. fieldPath string,
  355. errors *ValidationErrors,
  356. ) error {
  357. if list == nil {
  358. return nil
  359. }
  360. size := list.Len()
  361. // 验证元素数量
  362. if rules.MinItems != nil && uint64(size) < *rules.MinItems {
  363. defaultMsg := fmt.Sprintf("字段 %s 至少需要 %d 个元素", fieldPath, *rules.MinItems)
  364. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidLength,
  365. e.getErrorMessage(fieldRules, vctx, "min_items", defaultMsg)))
  366. }
  367. if rules.MaxItems != nil && uint64(size) > *rules.MaxItems {
  368. defaultMsg := fmt.Sprintf("字段 %s 最多允许 %d 个元素", fieldPath, *rules.MaxItems)
  369. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidLength,
  370. e.getErrorMessage(fieldRules, vctx, "max_items", defaultMsg)))
  371. }
  372. // 验证唯一性
  373. if rules.Unique != nil && *rules.Unique {
  374. seen := make(map[interface{}]bool)
  375. for i := 0; i < size; i++ {
  376. item := list.Get(i).Interface()
  377. if seen[item] {
  378. defaultMsg := fmt.Sprintf("字段 %s 包含重复元素", fieldPath)
  379. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue,
  380. e.getErrorMessage(fieldRules, vctx, "unique", defaultMsg)))
  381. break
  382. }
  383. seen[item] = true
  384. }
  385. }
  386. // TODO: 验证每个元素(需要递归调用validateFieldType)
  387. return nil
  388. }
  389. // validateMap 验证 map 字段
  390. func (e *Engine) validateMap(
  391. vctx *ValidationContext,
  392. fieldRules *validate.FieldRules,
  393. rules *validate.MapRules,
  394. mapValue protoreflect.Map,
  395. field protoreflect.FieldDescriptor,
  396. fieldPath string,
  397. errors *ValidationErrors,
  398. ) error {
  399. if mapValue == nil {
  400. return nil
  401. }
  402. size := mapValue.Len()
  403. // 验证键值对数量
  404. if rules.MinPairs != nil && uint64(size) < *rules.MinPairs {
  405. defaultMsg := fmt.Sprintf("字段 %s 至少需要 %d 个键值对", fieldPath, *rules.MinPairs)
  406. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidLength,
  407. e.getErrorMessage(fieldRules, vctx, "min_pairs", defaultMsg)))
  408. }
  409. if rules.MaxPairs != nil && uint64(size) > *rules.MaxPairs {
  410. defaultMsg := fmt.Sprintf("字段 %s 最多允许 %d 个键值对", fieldPath, *rules.MaxPairs)
  411. errors.Add(NewValidationError(fieldPath, ErrCodeInvalidLength,
  412. e.getErrorMessage(fieldRules, vctx, "max_pairs", defaultMsg)))
  413. }
  414. // TODO: 验证 keys 和 values
  415. return nil
  416. }