mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
fix(settings): preserve turnstile and omitted config fields
This commit is contained in:
parent
37c184aa45
commit
4a5d8aa702
4 changed files with 106 additions and 5 deletions
|
|
@ -77,6 +77,14 @@ class AllSetting {
|
|||
this.ldapDefaultExpiryDays = 0;
|
||||
this.ldapDefaultLimitIP = 0;
|
||||
|
||||
this.dbType = "sqlite";
|
||||
this.dbHost = "127.0.0.1";
|
||||
this.dbPort = "3306";
|
||||
this.dbUser = "";
|
||||
this.dbName = "3xui";
|
||||
|
||||
this.turnstileSiteKey = "";
|
||||
|
||||
if (data == null) {
|
||||
return
|
||||
}
|
||||
|
|
@ -86,4 +94,4 @@ class AllSetting {
|
|||
equals(other) {
|
||||
return ObjectUtil.equals(this, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/mhsanaei/3x-ui/v2/util/crypto"
|
||||
|
|
@ -66,15 +68,47 @@ func (a *SettingController) getDefaultSettings(c *gin.Context) {
|
|||
jsonObj(c, result, nil)
|
||||
}
|
||||
|
||||
func bindSettingUpdate(c *gin.Context) (*entity.AllSetting, map[string]struct{}, error) {
|
||||
allSetting := &entity.AllSetting{}
|
||||
presentKeys := map[string]struct{}{}
|
||||
|
||||
if c.ContentType() == "application/json" {
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := json.Unmarshal(body, allSetting); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var raw map[string]json.RawMessage
|
||||
if err := json.Unmarshal(body, &raw); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for key := range raw {
|
||||
presentKeys[key] = struct{}{}
|
||||
}
|
||||
return allSetting, presentKeys, nil
|
||||
}
|
||||
|
||||
if err := c.ShouldBind(allSetting); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.Request.ParseForm(); err == nil {
|
||||
for key := range c.Request.PostForm {
|
||||
presentKeys[key] = struct{}{}
|
||||
}
|
||||
}
|
||||
return allSetting, presentKeys, nil
|
||||
}
|
||||
|
||||
// updateSetting updates all settings with the provided data.
|
||||
func (a *SettingController) updateSetting(c *gin.Context) {
|
||||
allSetting := &entity.AllSetting{}
|
||||
err := c.ShouldBind(allSetting)
|
||||
allSetting, presentKeys, err := bindSettingUpdate(c)
|
||||
if err != nil {
|
||||
jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
|
||||
return
|
||||
}
|
||||
err = a.settingService.UpdateAllSetting(allSetting)
|
||||
err = a.settingService.UpdateAllSetting(allSetting, presentKeys)
|
||||
jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -977,7 +977,7 @@ func (s *SettingService) SetTurnstileSecretKey(value string) error {
|
|||
return s.setString("turnstileSecretKey", value)
|
||||
}
|
||||
|
||||
func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
|
||||
func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting, presentKeys map[string]struct{}) error {
|
||||
if err := allSetting.CheckValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -995,6 +995,11 @@ func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
|
|||
if key == "-" || key == "" {
|
||||
continue
|
||||
}
|
||||
if presentKeys != nil {
|
||||
if _, ok := presentKeys[key]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
fieldV := v.FieldByName(field.Name)
|
||||
settings[key] = fmt.Sprint(fieldV.Interface())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,3 +295,57 @@ func TestRoundTripNestedFormat(t *testing.T) {
|
|||
t.Error("expected 'tgBot' group in nested JSON")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateAllSettingPreservesOmittedFields(t *testing.T) {
|
||||
setupTestSettings(t)
|
||||
|
||||
svc := &SettingService{}
|
||||
if err := svc.setString("turnstileSiteKey", "site-key-123"); err != nil {
|
||||
t.Fatalf("setString turnstileSiteKey error: %v", err)
|
||||
}
|
||||
if err := svc.setString("dbType", "mariadb"); err != nil {
|
||||
t.Fatalf("setString dbType error: %v", err)
|
||||
}
|
||||
if err := svc.setString("dbHost", "10.0.0.8"); err != nil {
|
||||
t.Fatalf("setString dbHost error: %v", err)
|
||||
}
|
||||
|
||||
allSetting, err := svc.GetAllSetting()
|
||||
if err != nil {
|
||||
t.Fatalf("GetAllSetting error: %v", err)
|
||||
}
|
||||
allSetting.WebPort = 9443
|
||||
|
||||
presentKeys := map[string]struct{}{}
|
||||
for _, key := range []string{
|
||||
"webListen", "webDomain", "webPort", "webCertFile", "webKeyFile", "webBasePath", "sessionMaxAge",
|
||||
"pageSize", "expireDiff", "trafficDiff", "remarkModel", "datepicker",
|
||||
"tgBotEnable", "tgBotToken", "tgBotProxy", "tgBotAPIServer", "tgBotChatId", "tgRunTime", "tgBotBackup", "tgBotLoginNotify", "tgCpu", "tgLang",
|
||||
"timeLocation", "twoFactorEnable", "twoFactorToken",
|
||||
"subEnable", "subJsonEnable", "subTitle", "subSupportUrl", "subProfileUrl", "subAnnounce", "subEnableRouting", "subRoutingRules", "subListen", "subPort", "subPath", "subDomain", "subCertFile", "subKeyFile", "subUpdates", "externalTrafficInformEnable", "externalTrafficInformURI", "subEncrypt", "subShowInfo", "subURI", "subJsonPath", "subJsonURI", "subJsonFragment", "subJsonNoises", "subJsonMux", "subJsonRules",
|
||||
"ldapEnable", "ldapHost", "ldapPort", "ldapUseTLS", "ldapBindDN", "ldapPassword", "ldapBaseDN", "ldapUserFilter", "ldapUserAttr", "ldapVlessField", "ldapSyncCron", "ldapFlagField", "ldapTruthyValues", "ldapInvertFlag", "ldapInboundTags", "ldapAutoCreate", "ldapAutoDelete", "ldapDefaultTotalGB", "ldapDefaultExpiryDays", "ldapDefaultLimitIP",
|
||||
} {
|
||||
presentKeys[key] = struct{}{}
|
||||
}
|
||||
|
||||
if err := svc.UpdateAllSetting(allSetting, presentKeys); err != nil {
|
||||
t.Fatalf("UpdateAllSetting error: %v", err)
|
||||
}
|
||||
|
||||
settings, err := loadSettings()
|
||||
if err != nil {
|
||||
t.Fatalf("loadSettings error: %v", err)
|
||||
}
|
||||
if got := settings["turnstileSiteKey"]; got != "site-key-123" {
|
||||
t.Fatalf("expected turnstileSiteKey to be preserved, got %q", got)
|
||||
}
|
||||
if got := settings["dbType"]; got != "mariadb" {
|
||||
t.Fatalf("expected dbType to be preserved, got %q", got)
|
||||
}
|
||||
if got := settings["dbHost"]; got != "10.0.0.8" {
|
||||
t.Fatalf("expected dbHost to be preserved, got %q", got)
|
||||
}
|
||||
if got := settings["webPort"]; got != "9443" {
|
||||
t.Fatalf("expected webPort to be updated, got %q", got)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue