diff --git a/api/api.go b/api/api.go index fe4a4780..ddee8fc7 100644 --- a/api/api.go +++ b/api/api.go @@ -4,11 +4,28 @@ import ( "errors" "github.com/0xJacky/Nginx-UI/internal/logger" "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" val "github.com/go-playground/validator/v10" "net/http" "reflect" + "regexp" + "strings" ) +func init() { + if v, ok := binding.Validator.Engine().(*val.Validate); ok { + err := v.RegisterValidation("alphanumdash", func(fl val.FieldLevel) bool { + return regexp.MustCompile(`^[a-zA-Z0-9-]+$`).MatchString(fl.Field().String()) + }) + + if err != nil { + logger.Fatal(err) + } + return + } + logger.Fatal("binding validator engine is not initialized") +} + func ErrHandler(c *gin.Context, err error) { logger.GetLogger().Errorln(err) c.JSON(http.StatusInternalServerError, gin.H{ @@ -22,7 +39,6 @@ type ValidError struct { } func BindAndValid(c *gin.Context, target interface{}) bool { - errs := make(map[string]string) err := c.ShouldBindJSON(target) if err != nil { logger.Error("bind err", err) @@ -31,24 +47,23 @@ func BindAndValid(c *gin.Context, target interface{}) bool { ok := errors.As(err, &verrs) if !ok { - logger.Error("valid err", verrs) c.JSON(http.StatusNotAcceptable, gin.H{ "message": "Requested with wrong parameters", "code": http.StatusNotAcceptable, - "error": verrs, }) return false } + t := reflect.TypeOf(target).Elem() + errorsMap := make(map[string]interface{}) for _, value := range verrs { - t := reflect.ValueOf(target) - realType := t.Type().Elem() - field, _ := realType.FieldByName(value.StructField()) - errs[field.Tag.Get("json")] = value.Tag() + var path []string + getJsonPath(t, value.StructNamespace(), &path) + insertError(errorsMap, path, value.Tag()) } c.JSON(http.StatusNotAcceptable, gin.H{ - "errors": errs, + "errors": errorsMap, "message": "Requested with wrong parameters", "code": http.StatusNotAcceptable, }) @@ -58,3 +73,45 @@ func BindAndValid(c *gin.Context, target interface{}) bool { return true } + +// findField recursively finds the field in a nested struct +func getJsonPath(t reflect.Type, namespace string, path *[]string) { + fields := strings.Split(namespace, ".") + if len(fields) == 0 { + return + } + f, ok := t.FieldByName(fields[0]) + if !ok { + return + } + + *path = append(*path, f.Tag.Get("json")) + + if len(fields) > 1 { + subFields := strings.Join(fields[1:], ".") + getJsonPath(f.Type, subFields, path) + } +} + +// insertError inserts an error into the errors map +func insertError(errorsMap map[string]interface{}, path []string, errorTag string) { + if len(path) == 0 { + return + } + + jsonTag := path[0] + if len(path) == 1 { + // Last element in the path, set the error + errorsMap[jsonTag] = errorTag + return + } + + // Create a new map if necessary + if _, ok := errorsMap[jsonTag]; !ok { + errorsMap[jsonTag] = make(map[string]interface{}) + } + + // Recursively insert into the nested map + subMap, _ := errorsMap[jsonTag].(map[string]interface{}) + insertError(subMap, path[1:], errorTag) +} diff --git a/app/src/version.json b/app/src/version.json index ffe66b94..06a27421 100644 --- a/app/src/version.json +++ b/app/src/version.json @@ -1 +1 @@ -{"version":"2.0.0-beta.11","build_id":110,"total_build":314} \ No newline at end of file +{"version":"2.0.0-beta.11","build_id":111,"total_build":315} \ No newline at end of file diff --git a/app/src/views/certificate/WildcardCertificate.vue b/app/src/views/certificate/WildcardCertificate.vue index 3e858cb9..0c007e5b 100644 --- a/app/src/views/certificate/WildcardCertificate.vue +++ b/app/src/views/certificate/WildcardCertificate.vue @@ -43,7 +43,7 @@ const issueCert = () => { step.value++ modalVisible.value = true - refObtainCertLive.value.issue_cert(computedDomain.value, [computedDomain.value], () => { + refObtainCertLive.value.issue_cert(computedDomain.value, [computedDomain.value, domain.value], () => { message.success($gettext('Renew successfully')) emit('issued') }) diff --git a/app/version.json b/app/version.json index ffe66b94..06a27421 100644 --- a/app/version.json +++ b/app/version.json @@ -1 +1 @@ -{"version":"2.0.0-beta.11","build_id":110,"total_build":314} \ No newline at end of file +{"version":"2.0.0-beta.11","build_id":111,"total_build":315} \ No newline at end of file diff --git a/settings/casdoor.go b/settings/casdoor.go index 5a869ddc..d874699f 100644 --- a/settings/casdoor.go +++ b/settings/casdoor.go @@ -1,13 +1,13 @@ package settings type Casdoor struct { - Endpoint string `json:"endpoint"` - ClientId string `json:"client_id"` - ClientSecret string `json:"client_secret"` - Certificate string `json:"certificate"` - Organization string `json:"organization"` - Application string `json:"application"` - RedirectUri string `json:"redirect_uri"` + Endpoint string `json:"endpoint" protected:"true"` + ClientId string `json:"client_id" protected:"true"` + ClientSecret string `json:"client_secret" protected:"true"` + Certificate string `json:"certificate" protected:"true"` + Organization string `json:"organization" protected:"true"` + Application string `json:"application" protected:"true"` + RedirectUri string `json:"redirect_uri" protected:"true"` } var CasdoorSettings = Casdoor{ diff --git a/settings/nginx.go b/settings/nginx.go index 3727d348..62005fe9 100644 --- a/settings/nginx.go +++ b/settings/nginx.go @@ -1,8 +1,8 @@ package settings type Nginx struct { - AccessLogPath string `json:"access_log_path"` - ErrorLogPath string `json:"error_log_path"` + AccessLogPath string `json:"access_log_path" binding:"omitempty,file"` + ErrorLogPath string `json:"error_log_path" binding:"omitempty,file"` ConfigDir string `json:"config_dir" protected:"true"` PIDPath string `json:"pid_path" protected:"true"` TestConfigCmd string `json:"test_config_cmd" protected:"true"` diff --git a/settings/openai.go b/settings/openai.go index 79c4958c..140d619e 100644 --- a/settings/openai.go +++ b/settings/openai.go @@ -1,10 +1,10 @@ package settings type OpenAI struct { - BaseUrl string `json:"base_url"` - Token string `json:"token"` - Proxy string `json:"proxy"` - Model string `json:"model"` + BaseUrl string `json:"base_url" binding:"omitempty,url"` + Token string `json:"token" binding:"omitempty,alphanumdash"` + Proxy string `json:"proxy" binding:"omitempty,url"` + Model string `json:"model" binding:"omitempty,alphanumdash"` } var OpenAISettings = OpenAI{} diff --git a/settings/server.go b/settings/server.go index 97d15bd4..bacf914f 100644 --- a/settings/server.go +++ b/settings/server.go @@ -10,10 +10,10 @@ type Server struct { Email string `json:"email" protected:"true"` Database string `json:"database" protected:"true"` StartCmd string `json:"start_cmd" protected:"true"` - CADir string `json:"ca_dir"` + CADir string `json:"ca_dir" binding:"omitempty,url"` Demo bool `json:"demo" protected:"true"` PageSize int `json:"page_size" protected:"true"` - GithubProxy string `json:"github_proxy"` + GithubProxy string `json:"github_proxy" binding:"omitempty,url"` } var ServerSettings = Server{