|
@@ -2,22 +2,112 @@ package service
|
|
|
|
|
|
import (
|
|
|
_ "embed"
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "reflect"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
"time"
|
|
|
"x-ui/database"
|
|
|
"x-ui/database/model"
|
|
|
"x-ui/logger"
|
|
|
+ "x-ui/util/common"
|
|
|
"x-ui/util/random"
|
|
|
+ "x-ui/util/reflect_util"
|
|
|
+ "x-ui/web/entity"
|
|
|
)
|
|
|
|
|
|
//go:embed config.json
|
|
|
var xrayTemplateConfig string
|
|
|
|
|
|
+var defaultValueMap = map[string]string{
|
|
|
+ "xrayTemplateConfig": xrayTemplateConfig,
|
|
|
+ "webListen": "",
|
|
|
+ "webPort": "65432",
|
|
|
+ "webCertFile": "",
|
|
|
+ "webKeyFile": "",
|
|
|
+ "secret": random.Seq(32),
|
|
|
+ "webBasePath": "/",
|
|
|
+ "timeLocation": "Asia/Shanghai",
|
|
|
+}
|
|
|
+
|
|
|
type SettingService struct {
|
|
|
}
|
|
|
|
|
|
-func (s *SettingService) ClearSetting() error {
|
|
|
+func (s *SettingService) GetAllSetting() (*entity.AllSetting, error) {
|
|
|
+ db := database.GetDB()
|
|
|
+ settings := make([]*model.Setting, 0)
|
|
|
+ err := db.Model(model.Setting{}).Find(&settings).Error
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ allSetting := &entity.AllSetting{}
|
|
|
+ t := reflect.TypeOf(allSetting).Elem()
|
|
|
+ v := reflect.ValueOf(allSetting).Elem()
|
|
|
+ fields := reflect_util.GetFields(t)
|
|
|
+
|
|
|
+ setSetting := func(key, value string) (err error) {
|
|
|
+ defer func() {
|
|
|
+ panicErr := recover()
|
|
|
+ if panicErr != nil {
|
|
|
+ err = errors.New(fmt.Sprint(panicErr))
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ var found bool
|
|
|
+ var field reflect.StructField
|
|
|
+ for _, f := range fields {
|
|
|
+ if f.Tag.Get("json") == key {
|
|
|
+ field = f
|
|
|
+ found = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if !found {
|
|
|
+ // 有些设置自动生成,不需要返回到前端给用户修改
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ fieldV := v.FieldByName(field.Name)
|
|
|
+ switch t := fieldV.Interface().(type) {
|
|
|
+ case int:
|
|
|
+ n, err := strconv.ParseInt(value, 10, 32)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ fieldV.SetInt(n)
|
|
|
+ case string:
|
|
|
+ fieldV.SetString(value)
|
|
|
+ default:
|
|
|
+ return common.NewErrorf("unknown field %v type %v", key, t)
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ keyMap := map[string]bool{}
|
|
|
+ for _, setting := range settings {
|
|
|
+ err := setSetting(setting.Key, setting.Value)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ keyMap[setting.Key] = true
|
|
|
+ }
|
|
|
+
|
|
|
+ for key, value := range defaultValueMap {
|
|
|
+ if keyMap[key] {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ err := setSetting(key, value)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return allSetting, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (s *SettingService) ResetSettings() error {
|
|
|
db := database.GetDB()
|
|
|
return db.Delete(model.Setting{}).Error
|
|
|
}
|
|
@@ -48,18 +138,22 @@ func (s *SettingService) saveSetting(key string, value string) error {
|
|
|
return db.Save(setting).Error
|
|
|
}
|
|
|
|
|
|
-func (s *SettingService) getString(key string, defaultValue string) (string, error) {
|
|
|
+func (s *SettingService) getString(key string) (string, error) {
|
|
|
setting, err := s.getSetting(key)
|
|
|
if database.IsNotFound(err) {
|
|
|
- return defaultValue, nil
|
|
|
+ value, ok := defaultValueMap[key]
|
|
|
+ if !ok {
|
|
|
+ return "", common.NewErrorf("key <%v> not in defaultValueMap", key)
|
|
|
+ }
|
|
|
+ return value, nil
|
|
|
} else if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
return setting.Value, nil
|
|
|
}
|
|
|
|
|
|
-func (s *SettingService) getInt(key string, defaultValue int) (int, error) {
|
|
|
- str, err := s.getString(key, strconv.Itoa(defaultValue))
|
|
|
+func (s *SettingService) getInt(key string) (int, error) {
|
|
|
+ str, err := s.getString(key)
|
|
|
if err != nil {
|
|
|
return 0, err
|
|
|
}
|
|
@@ -67,29 +161,28 @@ func (s *SettingService) getInt(key string, defaultValue int) (int, error) {
|
|
|
}
|
|
|
|
|
|
func (s *SettingService) GetXrayConfigTemplate() (string, error) {
|
|
|
- return s.getString("xray_template_config", xrayTemplateConfig)
|
|
|
+ return s.getString("xrayTemplateConfig")
|
|
|
}
|
|
|
|
|
|
func (s *SettingService) GetListen() (string, error) {
|
|
|
- return s.getString("web_listen", "")
|
|
|
+ return s.getString("webListen")
|
|
|
}
|
|
|
|
|
|
func (s *SettingService) GetPort() (int, error) {
|
|
|
- return s.getInt("web_port", 65432)
|
|
|
+ return s.getInt("webPort")
|
|
|
}
|
|
|
|
|
|
func (s *SettingService) GetCertFile() (string, error) {
|
|
|
- return s.getString("web_cert_file", "")
|
|
|
+ return s.getString("webCertFile")
|
|
|
}
|
|
|
|
|
|
func (s *SettingService) GetKeyFile() (string, error) {
|
|
|
- return s.getString("web_key_file", "")
|
|
|
+ return s.getString("webKeyFile")
|
|
|
}
|
|
|
|
|
|
func (s *SettingService) GetSecret() ([]byte, error) {
|
|
|
- seq := random.Seq(32)
|
|
|
- secret, err := s.getString("secret", seq)
|
|
|
- if secret == seq {
|
|
|
+ secret, err := s.getString("secret")
|
|
|
+ if secret == defaultValueMap["secret"] {
|
|
|
err := s.saveSetting("secret", secret)
|
|
|
if err != nil {
|
|
|
logger.Warning("save secret failed:", err)
|
|
@@ -99,7 +192,7 @@ func (s *SettingService) GetSecret() ([]byte, error) {
|
|
|
}
|
|
|
|
|
|
func (s *SettingService) GetBasePath() (string, error) {
|
|
|
- basePath, err := s.getString("web_base_path", "/")
|
|
|
+ basePath, err := s.getString("webBasePath")
|
|
|
if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
@@ -113,15 +206,36 @@ func (s *SettingService) GetBasePath() (string, error) {
|
|
|
}
|
|
|
|
|
|
func (s *SettingService) GetTimeLocation() (*time.Location, error) {
|
|
|
- defaultLocation := "Asia/Shanghai"
|
|
|
- l, err := s.getString("time_location", defaultLocation)
|
|
|
+ l, err := s.getString("timeLocation")
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
location, err := time.LoadLocation(l)
|
|
|
if err != nil {
|
|
|
+ defaultLocation := defaultValueMap["timeLocation"]
|
|
|
logger.Errorf("location <%v> not exist, using default location: %v", l, defaultLocation)
|
|
|
return time.LoadLocation(defaultLocation)
|
|
|
}
|
|
|
return location, nil
|
|
|
}
|
|
|
+
|
|
|
+func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
|
|
|
+ if err := allSetting.CheckValid(); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ v := reflect.ValueOf(allSetting).Elem()
|
|
|
+ t := reflect.TypeOf(allSetting).Elem()
|
|
|
+ fields := reflect_util.GetFields(t)
|
|
|
+ errs := make([]error, 0)
|
|
|
+ for _, field := range fields {
|
|
|
+ key := field.Tag.Get("json")
|
|
|
+ fieldV := v.FieldByName(field.Name)
|
|
|
+ value := fmt.Sprint(fieldV.Interface())
|
|
|
+ err := s.saveSetting(key, value)
|
|
|
+ if err != nil {
|
|
|
+ errs = append(errs, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return common.Combine(errs...)
|
|
|
+}
|