baked_in.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. package validator
  2. import (
  3. "fmt"
  4. "net/url"
  5. "reflect"
  6. "strconv"
  7. "time"
  8. )
  9. // BakedInValidators is the default map of ValidationFunc
  10. // you can add, remove or even replace items to suite your needs,
  11. // or even disregard and use your own map if so desired.
  12. var BakedInValidators = map[string]ValidationFunc{
  13. "required": hasValue,
  14. "len": hasLengthOf,
  15. "min": hasMinOf,
  16. "max": hasMaxOf,
  17. "lt": isLt,
  18. "lte": isLte,
  19. "gt": isGt,
  20. "gte": isGte,
  21. "gtefield": isGteField,
  22. "gtfield": isGtField,
  23. "ltefield": isLteField,
  24. "ltfield": isLtField,
  25. "alpha": isAlpha,
  26. "alphanum": isAlphanum,
  27. "numeric": isNumeric,
  28. "number": isNumber,
  29. "hexadecimal": isHexadecimal,
  30. "hexcolor": isHexcolor,
  31. "rgb": isRgb,
  32. "rgba": isRgba,
  33. "hsl": isHsl,
  34. "hsla": isHsla,
  35. "email": isEmail,
  36. "url": isURL,
  37. "uri": isURI,
  38. }
  39. func isURI(top interface{}, current interface{}, field interface{}, param string) bool {
  40. st := reflect.ValueOf(field)
  41. switch st.Kind() {
  42. case reflect.String:
  43. _, err := url.ParseRequestURI(field.(string))
  44. return err == nil
  45. }
  46. panic(fmt.Sprintf("Bad field type %T", field))
  47. }
  48. func isURL(top interface{}, current interface{}, field interface{}, param string) bool {
  49. st := reflect.ValueOf(field)
  50. switch st.Kind() {
  51. case reflect.String:
  52. url, err := url.ParseRequestURI(field.(string))
  53. if err != nil {
  54. return false
  55. }
  56. if len(url.Scheme) == 0 {
  57. return false
  58. }
  59. return err == nil
  60. }
  61. panic(fmt.Sprintf("Bad field type %T", field))
  62. }
  63. func isEmail(top interface{}, current interface{}, field interface{}, param string) bool {
  64. return matchesRegex(emailRegex, field)
  65. }
  66. func isHsla(top interface{}, current interface{}, field interface{}, param string) bool {
  67. return matchesRegex(hslaRegex, field)
  68. }
  69. func isHsl(top interface{}, current interface{}, field interface{}, param string) bool {
  70. return matchesRegex(hslRegex, field)
  71. }
  72. func isRgba(top interface{}, current interface{}, field interface{}, param string) bool {
  73. return matchesRegex(rgbaRegex, field)
  74. }
  75. func isRgb(top interface{}, current interface{}, field interface{}, param string) bool {
  76. return matchesRegex(rgbRegex, field)
  77. }
  78. func isHexcolor(top interface{}, current interface{}, field interface{}, param string) bool {
  79. return matchesRegex(hexcolorRegex, field)
  80. }
  81. func isHexadecimal(top interface{}, current interface{}, field interface{}, param string) bool {
  82. return matchesRegex(hexadecimalRegex, field)
  83. }
  84. func isNumber(top interface{}, current interface{}, field interface{}, param string) bool {
  85. return matchesRegex(numberRegex, field)
  86. }
  87. func isNumeric(top interface{}, current interface{}, field interface{}, param string) bool {
  88. return matchesRegex(numericRegex, field)
  89. }
  90. func isAlphanum(top interface{}, current interface{}, field interface{}, param string) bool {
  91. return matchesRegex(alphaNumericRegex, field)
  92. }
  93. func isAlpha(top interface{}, current interface{}, field interface{}, param string) bool {
  94. return matchesRegex(alphaRegex, field)
  95. }
  96. func hasValue(top interface{}, current interface{}, field interface{}, param string) bool {
  97. st := reflect.ValueOf(field)
  98. switch st.Kind() {
  99. case reflect.Slice, reflect.Map, reflect.Array:
  100. return field != nil && int64(st.Len()) > 0
  101. default:
  102. return field != nil && field != reflect.Zero(reflect.TypeOf(field)).Interface()
  103. }
  104. }
  105. func isGteField(top interface{}, current interface{}, field interface{}, param string) bool {
  106. if current == nil {
  107. panic("struct not passed for cross validation")
  108. }
  109. currentVal := reflect.ValueOf(current)
  110. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  111. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  112. }
  113. var currentFielVal reflect.Value
  114. switch currentVal.Kind() {
  115. case reflect.Struct:
  116. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  117. currentFielVal = currentVal
  118. break
  119. }
  120. f := currentVal.FieldByName(param)
  121. if f.Kind() == reflect.Invalid {
  122. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  123. }
  124. currentFielVal = f
  125. default:
  126. currentFielVal = currentVal
  127. }
  128. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  129. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  130. }
  131. fv := reflect.ValueOf(field)
  132. switch fv.Kind() {
  133. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  134. return fv.Int() >= currentFielVal.Int()
  135. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  136. return fv.Uint() >= currentFielVal.Uint()
  137. case reflect.Float32, reflect.Float64:
  138. return fv.Float() >= currentFielVal.Float()
  139. case reflect.Struct:
  140. if fv.Type() == reflect.TypeOf(time.Time{}) {
  141. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  142. panic("Bad Top Level field type")
  143. }
  144. t := currentFielVal.Interface().(time.Time)
  145. fieldTime := field.(time.Time)
  146. return fieldTime.After(t) || fieldTime.Equal(t)
  147. }
  148. }
  149. panic(fmt.Sprintf("Bad field type %T", field))
  150. }
  151. func isGtField(top interface{}, current interface{}, field interface{}, param string) bool {
  152. if current == nil {
  153. panic("struct not passed for cross validation")
  154. }
  155. currentVal := reflect.ValueOf(current)
  156. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  157. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  158. }
  159. var currentFielVal reflect.Value
  160. switch currentVal.Kind() {
  161. case reflect.Struct:
  162. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  163. currentFielVal = currentVal
  164. break
  165. }
  166. f := currentVal.FieldByName(param)
  167. if f.Kind() == reflect.Invalid {
  168. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  169. }
  170. currentFielVal = f
  171. default:
  172. currentFielVal = currentVal
  173. }
  174. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  175. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  176. }
  177. fv := reflect.ValueOf(field)
  178. switch fv.Kind() {
  179. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  180. return fv.Int() > currentFielVal.Int()
  181. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  182. return fv.Uint() > currentFielVal.Uint()
  183. case reflect.Float32, reflect.Float64:
  184. return fv.Float() > currentFielVal.Float()
  185. case reflect.Struct:
  186. if fv.Type() == reflect.TypeOf(time.Time{}) {
  187. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  188. panic("Bad Top Level field type")
  189. }
  190. t := currentFielVal.Interface().(time.Time)
  191. fieldTime := field.(time.Time)
  192. return fieldTime.After(t)
  193. }
  194. }
  195. panic(fmt.Sprintf("Bad field type %T", field))
  196. }
  197. func isGte(top interface{}, current interface{}, field interface{}, param string) bool {
  198. st := reflect.ValueOf(field)
  199. switch st.Kind() {
  200. case reflect.String:
  201. p := asInt(param)
  202. return int64(len(st.String())) >= p
  203. case reflect.Slice, reflect.Map, reflect.Array:
  204. p := asInt(param)
  205. return int64(st.Len()) >= p
  206. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  207. p := asInt(param)
  208. return st.Int() >= p
  209. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  210. p := asUint(param)
  211. return st.Uint() >= p
  212. case reflect.Float32, reflect.Float64:
  213. p := asFloat(param)
  214. return st.Float() >= p
  215. case reflect.Struct:
  216. if st.Type() == reflect.TypeOf(time.Time{}) {
  217. now := time.Now().UTC()
  218. t := field.(time.Time)
  219. return t.After(now) || t.Equal(now)
  220. }
  221. }
  222. panic(fmt.Sprintf("Bad field type %T", field))
  223. }
  224. func isGt(top interface{}, current interface{}, field interface{}, param string) bool {
  225. st := reflect.ValueOf(field)
  226. switch st.Kind() {
  227. case reflect.String:
  228. p := asInt(param)
  229. return int64(len(st.String())) > p
  230. case reflect.Slice, reflect.Map, reflect.Array:
  231. p := asInt(param)
  232. return int64(st.Len()) > p
  233. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  234. p := asInt(param)
  235. return st.Int() > p
  236. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  237. p := asUint(param)
  238. return st.Uint() > p
  239. case reflect.Float32, reflect.Float64:
  240. p := asFloat(param)
  241. return st.Float() > p
  242. case reflect.Struct:
  243. if st.Type() == reflect.TypeOf(time.Time{}) {
  244. return field.(time.Time).After(time.Now().UTC())
  245. }
  246. }
  247. panic(fmt.Sprintf("Bad field type %T", field))
  248. }
  249. // length tests whether a variable's length is equal to a given
  250. // value. For strings it tests the number of characters whereas
  251. // for maps and slices it tests the number of items.
  252. func hasLengthOf(top interface{}, current interface{}, field interface{}, param string) bool {
  253. st := reflect.ValueOf(field)
  254. switch st.Kind() {
  255. case reflect.String:
  256. p := asInt(param)
  257. return int64(len(st.String())) == p
  258. case reflect.Slice, reflect.Map, reflect.Array:
  259. p := asInt(param)
  260. return int64(st.Len()) == p
  261. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  262. p := asInt(param)
  263. return st.Int() == p
  264. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  265. p := asUint(param)
  266. return st.Uint() == p
  267. case reflect.Float32, reflect.Float64:
  268. p := asFloat(param)
  269. return st.Float() == p
  270. }
  271. panic(fmt.Sprintf("Bad field type %T", field))
  272. }
  273. // min tests whether a variable value is larger or equal to a given
  274. // number. For number types, it's a simple lesser-than test; for
  275. // strings it tests the number of characters whereas for maps
  276. // and slices it tests the number of items.
  277. func hasMinOf(top interface{}, current interface{}, field interface{}, param string) bool {
  278. return isGte(top, current, field, param)
  279. }
  280. func isLteField(top interface{}, current interface{}, field interface{}, param string) bool {
  281. if current == nil {
  282. panic("struct not passed for cross validation")
  283. }
  284. currentVal := reflect.ValueOf(current)
  285. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  286. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  287. }
  288. var currentFielVal reflect.Value
  289. switch currentVal.Kind() {
  290. case reflect.Struct:
  291. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  292. currentFielVal = currentVal
  293. break
  294. }
  295. f := currentVal.FieldByName(param)
  296. if f.Kind() == reflect.Invalid {
  297. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  298. }
  299. currentFielVal = f
  300. default:
  301. currentFielVal = currentVal
  302. }
  303. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  304. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  305. }
  306. fv := reflect.ValueOf(field)
  307. switch fv.Kind() {
  308. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  309. return fv.Int() <= currentFielVal.Int()
  310. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  311. return fv.Uint() <= currentFielVal.Uint()
  312. case reflect.Float32, reflect.Float64:
  313. return fv.Float() <= currentFielVal.Float()
  314. case reflect.Struct:
  315. if fv.Type() == reflect.TypeOf(time.Time{}) {
  316. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  317. panic("Bad Top Level field type")
  318. }
  319. t := currentFielVal.Interface().(time.Time)
  320. fieldTime := field.(time.Time)
  321. return fieldTime.Before(t) || fieldTime.Equal(t)
  322. }
  323. }
  324. panic(fmt.Sprintf("Bad field type %T", field))
  325. }
  326. func isLtField(top interface{}, current interface{}, field interface{}, param string) bool {
  327. if current == nil {
  328. panic("struct not passed for cross validation")
  329. }
  330. currentVal := reflect.ValueOf(current)
  331. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  332. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  333. }
  334. var currentFielVal reflect.Value
  335. switch currentVal.Kind() {
  336. case reflect.Struct:
  337. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  338. currentFielVal = currentVal
  339. break
  340. }
  341. f := currentVal.FieldByName(param)
  342. if f.Kind() == reflect.Invalid {
  343. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  344. }
  345. currentFielVal = f
  346. default:
  347. currentFielVal = currentVal
  348. }
  349. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  350. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  351. }
  352. fv := reflect.ValueOf(field)
  353. switch fv.Kind() {
  354. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  355. return fv.Int() < currentFielVal.Int()
  356. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  357. return fv.Uint() < currentFielVal.Uint()
  358. case reflect.Float32, reflect.Float64:
  359. return fv.Float() < currentFielVal.Float()
  360. case reflect.Struct:
  361. if fv.Type() == reflect.TypeOf(time.Time{}) {
  362. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  363. panic("Bad Top Level field type")
  364. }
  365. t := currentFielVal.Interface().(time.Time)
  366. fieldTime := field.(time.Time)
  367. return fieldTime.Before(t)
  368. }
  369. }
  370. panic(fmt.Sprintf("Bad field type %T", field))
  371. }
  372. func isLte(top interface{}, current interface{}, field interface{}, param string) bool {
  373. st := reflect.ValueOf(field)
  374. switch st.Kind() {
  375. case reflect.String:
  376. p := asInt(param)
  377. return int64(len(st.String())) <= p
  378. case reflect.Slice, reflect.Map, reflect.Array:
  379. p := asInt(param)
  380. return int64(st.Len()) <= p
  381. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  382. p := asInt(param)
  383. return st.Int() <= p
  384. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  385. p := asUint(param)
  386. return st.Uint() <= p
  387. case reflect.Float32, reflect.Float64:
  388. p := asFloat(param)
  389. return st.Float() <= p
  390. case reflect.Struct:
  391. if st.Type() == reflect.TypeOf(time.Time{}) {
  392. now := time.Now().UTC()
  393. t := field.(time.Time)
  394. return t.Before(now) || t.Equal(now)
  395. }
  396. }
  397. panic(fmt.Sprintf("Bad field type %T", field))
  398. }
  399. func isLt(top interface{}, current interface{}, field interface{}, param string) bool {
  400. st := reflect.ValueOf(field)
  401. switch st.Kind() {
  402. case reflect.String:
  403. p := asInt(param)
  404. return int64(len(st.String())) < p
  405. case reflect.Slice, reflect.Map, reflect.Array:
  406. p := asInt(param)
  407. return int64(st.Len()) < p
  408. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  409. p := asInt(param)
  410. return st.Int() < p
  411. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  412. p := asUint(param)
  413. return st.Uint() < p
  414. case reflect.Float32, reflect.Float64:
  415. p := asFloat(param)
  416. return st.Float() < p
  417. case reflect.Struct:
  418. if st.Type() == reflect.TypeOf(time.Time{}) {
  419. return field.(time.Time).Before(time.Now().UTC())
  420. }
  421. }
  422. panic(fmt.Sprintf("Bad field type %T", field))
  423. }
  424. // max tests whether a variable value is lesser than a given
  425. // value. For numbers, it's a simple lesser-than test; for
  426. // strings it tests the number of characters whereas for maps
  427. // and slices it tests the number of items.
  428. func hasMaxOf(top interface{}, current interface{}, field interface{}, param string) bool {
  429. return isLte(top, current, field, param)
  430. }
  431. // asInt retuns the parameter as a int64
  432. // or panics if it can't convert
  433. func asInt(param string) int64 {
  434. i, err := strconv.ParseInt(param, 0, 64)
  435. panicIf(err)
  436. return i
  437. }
  438. // asUint returns the parameter as a uint64
  439. // or panics if it can't convert
  440. func asUint(param string) uint64 {
  441. i, err := strconv.ParseUint(param, 0, 64)
  442. panicIf(err)
  443. return i
  444. }
  445. // asFloat returns the parameter as a float64
  446. // or panics if it can't convert
  447. func asFloat(param string) float64 {
  448. i, err := strconv.ParseFloat(param, 64)
  449. panicIf(err)
  450. return i
  451. }
  452. func panicIf(err error) {
  453. if err != nil {
  454. panic(err.Error())
  455. }
  456. }