Skip to content

Commit d67b842

Browse files
committed
enhance: validate settings value before save
1 parent d70e37c commit d67b842

File tree

8 files changed

+83
-26
lines changed

8 files changed

+83
-26
lines changed

api/api.go

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,28 @@ import (
44
"errors"
55
"github.com/0xJacky/Nginx-UI/internal/logger"
66
"github.com/gin-gonic/gin"
7+
"github.com/gin-gonic/gin/binding"
78
val "github.com/go-playground/validator/v10"
89
"net/http"
910
"reflect"
11+
"regexp"
12+
"strings"
1013
)
1114

15+
func init() {
16+
if v, ok := binding.Validator.Engine().(*val.Validate); ok {
17+
err := v.RegisterValidation("alphanumdash", func(fl val.FieldLevel) bool {
18+
return regexp.MustCompile(`^[a-zA-Z0-9-]+$`).MatchString(fl.Field().String())
19+
})
20+
21+
if err != nil {
22+
logger.Fatal(err)
23+
}
24+
return
25+
}
26+
logger.Fatal("binding validator engine is not initialized")
27+
}
28+
1229
func ErrHandler(c *gin.Context, err error) {
1330
logger.GetLogger().Errorln(err)
1431
c.JSON(http.StatusInternalServerError, gin.H{
@@ -22,7 +39,6 @@ type ValidError struct {
2239
}
2340

2441
func BindAndValid(c *gin.Context, target interface{}) bool {
25-
errs := make(map[string]string)
2642
err := c.ShouldBindJSON(target)
2743
if err != nil {
2844
logger.Error("bind err", err)
@@ -31,24 +47,23 @@ func BindAndValid(c *gin.Context, target interface{}) bool {
3147
ok := errors.As(err, &verrs)
3248

3349
if !ok {
34-
logger.Error("valid err", verrs)
3550
c.JSON(http.StatusNotAcceptable, gin.H{
3651
"message": "Requested with wrong parameters",
3752
"code": http.StatusNotAcceptable,
38-
"error": verrs,
3953
})
4054
return false
4155
}
4256

57+
t := reflect.TypeOf(target).Elem()
58+
errorsMap := make(map[string]interface{})
4359
for _, value := range verrs {
44-
t := reflect.ValueOf(target)
45-
realType := t.Type().Elem()
46-
field, _ := realType.FieldByName(value.StructField())
47-
errs[field.Tag.Get("json")] = value.Tag()
60+
var path []string
61+
getJsonPath(t, value.StructNamespace(), &path)
62+
insertError(errorsMap, path, value.Tag())
4863
}
4964

5065
c.JSON(http.StatusNotAcceptable, gin.H{
51-
"errors": errs,
66+
"errors": errorsMap,
5267
"message": "Requested with wrong parameters",
5368
"code": http.StatusNotAcceptable,
5469
})
@@ -58,3 +73,45 @@ func BindAndValid(c *gin.Context, target interface{}) bool {
5873

5974
return true
6075
}
76+
77+
// findField recursively finds the field in a nested struct
78+
func getJsonPath(t reflect.Type, namespace string, path *[]string) {
79+
fields := strings.Split(namespace, ".")
80+
if len(fields) == 0 {
81+
return
82+
}
83+
f, ok := t.FieldByName(fields[0])
84+
if !ok {
85+
return
86+
}
87+
88+
*path = append(*path, f.Tag.Get("json"))
89+
90+
if len(fields) > 1 {
91+
subFields := strings.Join(fields[1:], ".")
92+
getJsonPath(f.Type, subFields, path)
93+
}
94+
}
95+
96+
// insertError inserts an error into the errors map
97+
func insertError(errorsMap map[string]interface{}, path []string, errorTag string) {
98+
if len(path) == 0 {
99+
return
100+
}
101+
102+
jsonTag := path[0]
103+
if len(path) == 1 {
104+
// Last element in the path, set the error
105+
errorsMap[jsonTag] = errorTag
106+
return
107+
}
108+
109+
// Create a new map if necessary
110+
if _, ok := errorsMap[jsonTag]; !ok {
111+
errorsMap[jsonTag] = make(map[string]interface{})
112+
}
113+
114+
// Recursively insert into the nested map
115+
subMap, _ := errorsMap[jsonTag].(map[string]interface{})
116+
insertError(subMap, path[1:], errorTag)
117+
}

app/src/version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"version":"2.0.0-beta.11","build_id":110,"total_build":314}
1+
{"version":"2.0.0-beta.11","build_id":111,"total_build":315}

app/src/views/certificate/WildcardCertificate.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const issueCert = () => {
4343
step.value++
4444
modalVisible.value = true
4545
46-
refObtainCertLive.value.issue_cert(computedDomain.value, [computedDomain.value], () => {
46+
refObtainCertLive.value.issue_cert(computedDomain.value, [computedDomain.value, domain.value], () => {
4747
message.success($gettext('Renew successfully'))
4848
emit('issued')
4949
})

app/version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"version":"2.0.0-beta.11","build_id":110,"total_build":314}
1+
{"version":"2.0.0-beta.11","build_id":111,"total_build":315}

settings/casdoor.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package settings
22

33
type Casdoor struct {
4-
Endpoint string `json:"endpoint"`
5-
ClientId string `json:"client_id"`
6-
ClientSecret string `json:"client_secret"`
7-
Certificate string `json:"certificate"`
8-
Organization string `json:"organization"`
9-
Application string `json:"application"`
10-
RedirectUri string `json:"redirect_uri"`
4+
Endpoint string `json:"endpoint" protected:"true"`
5+
ClientId string `json:"client_id" protected:"true"`
6+
ClientSecret string `json:"client_secret" protected:"true"`
7+
Certificate string `json:"certificate" protected:"true"`
8+
Organization string `json:"organization" protected:"true"`
9+
Application string `json:"application" protected:"true"`
10+
RedirectUri string `json:"redirect_uri" protected:"true"`
1111
}
1212

1313
var CasdoorSettings = Casdoor{

settings/nginx.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package settings
22

33
type Nginx struct {
4-
AccessLogPath string `json:"access_log_path"`
5-
ErrorLogPath string `json:"error_log_path"`
4+
AccessLogPath string `json:"access_log_path" binding:"omitempty,file"`
5+
ErrorLogPath string `json:"error_log_path" binding:"omitempty,file"`
66
ConfigDir string `json:"config_dir" protected:"true"`
77
PIDPath string `json:"pid_path" protected:"true"`
88
TestConfigCmd string `json:"test_config_cmd" protected:"true"`

settings/openai.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package settings
22

33
type OpenAI struct {
4-
BaseUrl string `json:"base_url"`
5-
Token string `json:"token"`
6-
Proxy string `json:"proxy"`
7-
Model string `json:"model"`
4+
BaseUrl string `json:"base_url" binding:"omitempty,url"`
5+
Token string `json:"token" binding:"omitempty,alphanumdash"`
6+
Proxy string `json:"proxy" binding:"omitempty,url"`
7+
Model string `json:"model" binding:"omitempty,alphanumdash"`
88
}
99

1010
var OpenAISettings = OpenAI{}

settings/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ type Server struct {
1010
Email string `json:"email" protected:"true"`
1111
Database string `json:"database" protected:"true"`
1212
StartCmd string `json:"start_cmd" protected:"true"`
13-
CADir string `json:"ca_dir"`
13+
CADir string `json:"ca_dir" binding:"omitempty,url"`
1414
Demo bool `json:"demo" protected:"true"`
1515
PageSize int `json:"page_size" protected:"true"`
16-
GithubProxy string `json:"github_proxy"`
16+
GithubProxy string `json:"github_proxy" binding:"omitempty,url"`
1717
}
1818

1919
var ServerSettings = Server{

0 commit comments

Comments
 (0)