api.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package api
  2. import (
  3. "errors"
  4. "github.com/uozi-tech/cosy/logger"
  5. "github.com/0xJacky/Nginx-UI/model"
  6. "github.com/gin-gonic/gin"
  7. "github.com/go-playground/validator/v10"
  8. "net/http"
  9. "reflect"
  10. "regexp"
  11. "strings"
  12. )
  13. func CurrentUser(c *gin.Context) *model.User {
  14. return c.MustGet("user").(*model.User)
  15. }
  16. func ErrHandler(c *gin.Context, err error) {
  17. logger.GetLogger().Errorln(err)
  18. c.JSON(http.StatusInternalServerError, gin.H{
  19. "message": err.Error(),
  20. })
  21. }
  22. type ValidError struct {
  23. Key string
  24. Message string
  25. }
  26. func BindAndValid(c *gin.Context, target interface{}) bool {
  27. err := c.ShouldBindJSON(target)
  28. if err != nil {
  29. logger.Error("bind err", err)
  30. var verrs validator.ValidationErrors
  31. ok := errors.As(err, &verrs)
  32. if !ok {
  33. c.JSON(http.StatusNotAcceptable, gin.H{
  34. "message": "Requested with wrong parameters",
  35. "code": http.StatusNotAcceptable,
  36. })
  37. return false
  38. }
  39. t := reflect.TypeOf(target).Elem()
  40. errorsMap := make(map[string]interface{})
  41. for _, value := range verrs {
  42. var path []string
  43. namespace := strings.Split(value.StructNamespace(), ".")
  44. // logger.Debug(t.Name(), namespace)
  45. if t.Name() != "" && len(namespace) > 1 {
  46. namespace = namespace[1:]
  47. }
  48. getJsonPath(t, namespace, &path)
  49. insertError(errorsMap, path, value.Tag())
  50. }
  51. c.JSON(http.StatusNotAcceptable, gin.H{
  52. "errors": errorsMap,
  53. "message": "Requested with wrong parameters",
  54. "code": http.StatusNotAcceptable,
  55. })
  56. return false
  57. }
  58. return true
  59. }
  60. // findField recursively finds the field in a nested struct
  61. func getJsonPath(t reflect.Type, fields []string, path *[]string) {
  62. field := fields[0]
  63. // used in case of array
  64. var index string
  65. if field[len(field)-1] == ']' {
  66. re := regexp.MustCompile(`(\w+)\[(\d+)\]`)
  67. matches := re.FindStringSubmatch(field)
  68. if len(matches) > 2 {
  69. field = matches[1]
  70. index = matches[2]
  71. }
  72. }
  73. f, ok := t.FieldByName(field)
  74. if !ok {
  75. return
  76. }
  77. *path = append(*path, f.Tag.Get("json"))
  78. if index != "" {
  79. *path = append(*path, index)
  80. }
  81. if len(fields) > 1 {
  82. subFields := fields[1:]
  83. getJsonPath(f.Type, subFields, path)
  84. }
  85. }
  86. // insertError inserts an error into the errors map
  87. func insertError(errorsMap map[string]interface{}, path []string, errorTag string) {
  88. if len(path) == 0 {
  89. return
  90. }
  91. jsonTag := path[0]
  92. if len(path) == 1 {
  93. // Last element in the path, set the error
  94. errorsMap[jsonTag] = errorTag
  95. return
  96. }
  97. // Create a new map if necessary
  98. if _, ok := errorsMap[jsonTag]; !ok {
  99. errorsMap[jsonTag] = make(map[string]interface{})
  100. }
  101. // Recursively insert into the nested map
  102. subMap, _ := errorsMap[jsonTag].(map[string]interface{})
  103. insertError(subMap, path[1:], errorTag)
  104. }