mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-02-28 05:02:59 +00:00
266 lines
9.6 KiB
Go
266 lines
9.6 KiB
Go
package model
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strconv"
|
|
"sync"
|
|
|
|
"github.com/mhsanaei/3x-ui/v2/util/random"
|
|
)
|
|
|
|
// AppSettings is the authoritative typed settings row.
|
|
// It mirrors the historical key/value settings keys via `setting` tags.
|
|
type AppSettings struct {
|
|
ID int `gorm:"primaryKey;autoIncrement"`
|
|
CreatedAt int64 `gorm:"autoCreateTime:milli"`
|
|
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
|
|
|
|
XrayTemplateConfig string `gorm:"type:text" setting:"xrayTemplateConfig"`
|
|
WebListen string `setting:"webListen"`
|
|
WebDomain string `setting:"webDomain"`
|
|
WebPort int `setting:"webPort"`
|
|
WebCertFile string `setting:"webCertFile"`
|
|
WebKeyFile string `setting:"webKeyFile"`
|
|
Secret string `setting:"secret"`
|
|
WebBasePath string `setting:"webBasePath"`
|
|
SessionMaxAge int `setting:"sessionMaxAge"`
|
|
PageSize int `setting:"pageSize"`
|
|
ExpireDiff int `setting:"expireDiff"`
|
|
TrafficDiff int `setting:"trafficDiff"`
|
|
RemarkModel string `setting:"remarkModel"`
|
|
TimeLocation string `setting:"timeLocation"`
|
|
|
|
TgBotEnable bool `setting:"tgBotEnable"`
|
|
TgBotToken string `setting:"tgBotToken"`
|
|
TgBotProxy string `setting:"tgBotProxy"`
|
|
TgBotAPIServer string `setting:"tgBotAPIServer"`
|
|
TgBotChatID string `setting:"tgBotChatId"`
|
|
TgRunTime string `setting:"tgRunTime"`
|
|
TgBotBackup bool `setting:"tgBotBackup"`
|
|
TgBotLoginNotify bool `setting:"tgBotLoginNotify"`
|
|
TgCPU int `setting:"tgCpu"`
|
|
TgLang string `setting:"tgLang"`
|
|
|
|
TwoFactorEnable bool `setting:"twoFactorEnable"`
|
|
TwoFactorToken string `setting:"twoFactorToken"`
|
|
|
|
SubEnable bool `setting:"subEnable"`
|
|
SubJSONEnable bool `setting:"subJsonEnable"`
|
|
SubTitle string `setting:"subTitle"`
|
|
SubSupportURL string `setting:"subSupportUrl"`
|
|
SubProfileURL string `setting:"subProfileUrl"`
|
|
SubAnnounce string `setting:"subAnnounce"`
|
|
SubEnableRouting bool `setting:"subEnableRouting"`
|
|
SubRoutingRules string `gorm:"type:text" setting:"subRoutingRules"`
|
|
SubListen string `setting:"subListen"`
|
|
SubPort int `setting:"subPort"`
|
|
SubPath string `setting:"subPath"`
|
|
SubDomain string `setting:"subDomain"`
|
|
SubCertFile string `setting:"subCertFile"`
|
|
SubKeyFile string `setting:"subKeyFile"`
|
|
SubUpdates string `setting:"subUpdates"`
|
|
SubEncrypt bool `setting:"subEncrypt"`
|
|
SubShowInfo bool `setting:"subShowInfo"`
|
|
SubURI string `setting:"subURI"`
|
|
SubJSONPath string `setting:"subJsonPath"`
|
|
SubJSONURI string `setting:"subJsonURI"`
|
|
SubJSONFragment string `setting:"subJsonFragment"`
|
|
SubJSONNoises string `setting:"subJsonNoises"`
|
|
SubJSONMux string `setting:"subJsonMux"`
|
|
SubJSONRules string `setting:"subJsonRules"`
|
|
Datepicker string `setting:"datepicker"`
|
|
|
|
Warp string `setting:"warp"`
|
|
ExternalTrafficInformEnable bool `setting:"externalTrafficInformEnable"`
|
|
ExternalTrafficInformURI string `setting:"externalTrafficInformURI"`
|
|
XrayOutboundTestURL string `setting:"xrayOutboundTestUrl"`
|
|
|
|
LdapEnable bool `setting:"ldapEnable"`
|
|
LdapHost string `setting:"ldapHost"`
|
|
LdapPort int `setting:"ldapPort"`
|
|
LdapUseTLS bool `setting:"ldapUseTLS"`
|
|
LdapBindDN string `setting:"ldapBindDN"`
|
|
LdapPassword string `setting:"ldapPassword"`
|
|
LdapBaseDN string `setting:"ldapBaseDN"`
|
|
LdapUserFilter string `setting:"ldapUserFilter"`
|
|
LdapUserAttr string `setting:"ldapUserAttr"`
|
|
LdapVlessField string `setting:"ldapVlessField"`
|
|
LdapSyncCron string `setting:"ldapSyncCron"`
|
|
LdapFlagField string `setting:"ldapFlagField"`
|
|
LdapTruthyValues string `setting:"ldapTruthyValues"`
|
|
LdapInvertFlag bool `setting:"ldapInvertFlag"`
|
|
LdapInboundTags string `setting:"ldapInboundTags"`
|
|
LdapAutoCreate bool `setting:"ldapAutoCreate"`
|
|
LdapAutoDelete bool `setting:"ldapAutoDelete"`
|
|
LdapDefaultTotalGB int `setting:"ldapDefaultTotalGB"`
|
|
LdapDefaultExpiryDays int `setting:"ldapDefaultExpiryDays"`
|
|
LdapDefaultLimitIP int `setting:"ldapDefaultLimitIP"`
|
|
}
|
|
|
|
func (AppSettings) TableName() string {
|
|
return "app_settings"
|
|
}
|
|
|
|
var (
|
|
appSettingsFieldMapOnce sync.Once
|
|
appSettingsFieldMap map[string]int
|
|
)
|
|
|
|
func buildAppSettingsFieldMap() {
|
|
appSettingsFieldMap = make(map[string]int)
|
|
t := reflect.TypeOf(AppSettings{})
|
|
for i := 0; i < t.NumField(); i++ {
|
|
f := t.Field(i)
|
|
key := f.Tag.Get("setting")
|
|
if key == "" {
|
|
continue
|
|
}
|
|
appSettingsFieldMap[key] = i
|
|
}
|
|
}
|
|
|
|
func getAppSettingsFieldMap() map[string]int {
|
|
appSettingsFieldMapOnce.Do(buildAppSettingsFieldMap)
|
|
return appSettingsFieldMap
|
|
}
|
|
|
|
// DefaultSettingValues returns canonical defaults for settings keys.
|
|
func DefaultSettingValues(xrayTemplateConfig string) map[string]string {
|
|
return map[string]string{
|
|
"xrayTemplateConfig": xrayTemplateConfig,
|
|
"webListen": "",
|
|
"webDomain": "",
|
|
"webPort": "2053",
|
|
"webCertFile": "",
|
|
"webKeyFile": "",
|
|
"secret": random.Seq(32),
|
|
"webBasePath": "/",
|
|
"sessionMaxAge": "360",
|
|
"pageSize": "25",
|
|
"expireDiff": "0",
|
|
"trafficDiff": "0",
|
|
"remarkModel": "-ieo",
|
|
"timeLocation": "Local",
|
|
"tgBotEnable": "false",
|
|
"tgBotToken": "",
|
|
"tgBotProxy": "",
|
|
"tgBotAPIServer": "",
|
|
"tgBotChatId": "",
|
|
"tgRunTime": "@daily",
|
|
"tgBotBackup": "false",
|
|
"tgBotLoginNotify": "true",
|
|
"tgCpu": "80",
|
|
"tgLang": "en-US",
|
|
"twoFactorEnable": "false",
|
|
"twoFactorToken": "",
|
|
"subEnable": "true",
|
|
"subJsonEnable": "false",
|
|
"subTitle": "",
|
|
"subSupportUrl": "",
|
|
"subProfileUrl": "",
|
|
"subAnnounce": "",
|
|
"subEnableRouting": "true",
|
|
"subRoutingRules": "",
|
|
"subListen": "",
|
|
"subPort": "2096",
|
|
"subPath": "/sub/",
|
|
"subDomain": "",
|
|
"subCertFile": "",
|
|
"subKeyFile": "",
|
|
"subUpdates": "12",
|
|
"subEncrypt": "true",
|
|
"subShowInfo": "true",
|
|
"subURI": "",
|
|
"subJsonPath": "/json/",
|
|
"subJsonURI": "",
|
|
"subJsonFragment": "",
|
|
"subJsonNoises": "",
|
|
"subJsonMux": "",
|
|
"subJsonRules": "",
|
|
"datepicker": "gregorian",
|
|
"warp": "",
|
|
"externalTrafficInformEnable": "false",
|
|
"externalTrafficInformURI": "",
|
|
"xrayOutboundTestUrl": "https://www.google.com/generate_204",
|
|
"ldapEnable": "false",
|
|
"ldapHost": "",
|
|
"ldapPort": "389",
|
|
"ldapUseTLS": "false",
|
|
"ldapBindDN": "",
|
|
"ldapPassword": "",
|
|
"ldapBaseDN": "",
|
|
"ldapUserFilter": "(objectClass=person)",
|
|
"ldapUserAttr": "mail",
|
|
"ldapVlessField": "vless_enabled",
|
|
"ldapSyncCron": "@every 1m",
|
|
"ldapFlagField": "",
|
|
"ldapTruthyValues": "true,1,yes,on",
|
|
"ldapInvertFlag": "false",
|
|
"ldapInboundTags": "",
|
|
"ldapAutoCreate": "false",
|
|
"ldapAutoDelete": "false",
|
|
"ldapDefaultTotalGB": "0",
|
|
"ldapDefaultExpiryDays": "0",
|
|
"ldapDefaultLimitIP": "0",
|
|
}
|
|
}
|
|
|
|
// NewDefaultAppSettings creates a settings row initialized with default values.
|
|
func NewDefaultAppSettings(xrayTemplateConfig string) *AppSettings {
|
|
cfg := &AppSettings{}
|
|
defaults := DefaultSettingValues(xrayTemplateConfig)
|
|
for key, value := range defaults {
|
|
_, _ = cfg.SetByKey(key, value)
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
// GetByKey returns a string representation of a settings key value.
|
|
func (s *AppSettings) GetByKey(key string) (string, bool, error) {
|
|
idx, ok := getAppSettingsFieldMap()[key]
|
|
if !ok {
|
|
return "", false, nil
|
|
}
|
|
v := reflect.ValueOf(s).Elem().Field(idx)
|
|
switch v.Kind() {
|
|
case reflect.String:
|
|
return v.String(), true, nil
|
|
case reflect.Bool:
|
|
return strconv.FormatBool(v.Bool()), true, nil
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return strconv.FormatInt(v.Int(), 10), true, nil
|
|
default:
|
|
return "", true, fmt.Errorf("unsupported settings field kind for key %s: %s", key, v.Kind())
|
|
}
|
|
}
|
|
|
|
// SetByKey sets a settings value by historical key name.
|
|
func (s *AppSettings) SetByKey(key string, value string) (bool, error) {
|
|
idx, ok := getAppSettingsFieldMap()[key]
|
|
if !ok {
|
|
return false, nil
|
|
}
|
|
v := reflect.ValueOf(s).Elem().Field(idx)
|
|
switch v.Kind() {
|
|
case reflect.String:
|
|
v.SetString(value)
|
|
return true, nil
|
|
case reflect.Bool:
|
|
parsed, err := strconv.ParseBool(value)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
v.SetBool(parsed)
|
|
return true, nil
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
parsed, err := strconv.ParseInt(value, 10, 64)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
v.SetInt(parsed)
|
|
return true, nil
|
|
default:
|
|
return true, fmt.Errorf("unsupported settings field kind for key %s: %s", key, v.Kind())
|
|
}
|
|
}
|