load from database

This commit is contained in:
Alireza Ahmadi
2024-12-25 10:57:17 +01:00
parent 7a047daf6f
commit ed48cdca33
13 changed files with 290 additions and 130 deletions
+3 -3
View File
@@ -16,7 +16,7 @@ type APIHandler struct {
service.ConfigService service.ConfigService
service.ClientService service.ClientService
service.TlsService service.TlsService
service.InDataService service.InboundService
service.PanelService service.PanelService
service.StatsService service.StatsService
service.ServerService service.ServerService
@@ -207,7 +207,7 @@ func (a *APIHandler) loadData(c *gin.Context) (interface{}, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
inData, err := a.InDataService.GetAll() inbounds, err := a.InboundService.GetAll()
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -218,7 +218,7 @@ func (a *APIHandler) loadData(c *gin.Context) (interface{}, error) {
data["config"] = *config data["config"] = *config
data["clients"] = clients data["clients"] = clients
data["tls"] = tlsConfigs data["tls"] = tlsConfigs
data["inData"] = inData data["inbounds"] = inbounds
data["subURI"] = subURI data["subURI"] = subURI
data["onlines"] = onlines data["onlines"] = onlines
} else { } else {
+13 -8
View File
@@ -16,11 +16,12 @@ import (
type APP struct { type APP struct {
service.SettingService service.SettingService
webServer *web.Server configService *service.ConfigService
subServer *sub.Server webServer *web.Server
cronJob *cronjob.CronJob subServer *sub.Server
logger *logging.Logger cronJob *cronjob.CronJob
core *core.Core logger *logging.Logger
core *core.Core
} }
func NewApp() *APP { func NewApp() *APP {
@@ -46,8 +47,8 @@ func (a *APP) Init() error {
a.webServer = web.NewServer() a.webServer = web.NewServer()
a.subServer = sub.NewServer() a.subServer = sub.NewServer()
configService := service.NewConfigService(a.core) a.configService = service.NewConfigService(a.core)
err = configService.InitConfig() err = a.configService.InitConfig()
if err != nil { if err != nil {
return err return err
} }
@@ -80,7 +81,7 @@ func (a *APP) Start() error {
return err return err
} }
err = a.core.Start() err = a.configService.StartCore()
if err != nil { if err != nil {
logger.Error(err) logger.Error(err)
} }
@@ -98,6 +99,10 @@ func (a *APP) Stop() {
if err != nil { if err != nil {
logger.Warning("stop Web Server err:", err) logger.Warning("stop Web Server err:", err)
} }
err = a.configService.StopCore()
if err != nil {
logger.Warning("stop Core err:", err)
}
} }
func (a *APP) initLog() { func (a *APP) initLog() {
+6 -1
View File
@@ -4,6 +4,7 @@ import (
_ "embed" _ "embed"
"fmt" "fmt"
"os" "os"
"path/filepath"
"strings" "strings"
) )
@@ -59,7 +60,11 @@ func GetBinFolderPath() string {
func GetDBFolderPath() string { func GetDBFolderPath() string {
dbFolderPath := os.Getenv("SUI_DB_FOLDER") dbFolderPath := os.Getenv("SUI_DB_FOLDER")
if dbFolderPath == "" { if dbFolderPath == "" {
dbFolderPath = "/usr/local/s-ui/db" dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
dbFolderPath = "/usr/local/s-ui/db"
}
dbFolderPath = dir + "/db"
} }
return dbFolderPath return dbFolderPath
} }
+2 -19
View File
@@ -2,8 +2,6 @@ package core
import ( import (
"context" "context"
"os"
"s-ui/config"
"s-ui/logger" "s-ui/logger"
sb "github.com/sagernet/sing-box" sb "github.com/sagernet/sing-box"
@@ -49,14 +47,9 @@ func (c *Core) GetInstance() *Box {
return c.instance return c.instance
} }
func (c *Core) Start() error { func (c *Core) Start(sbConfig []byte) error {
filepath := config.GetBinFolderPath() + "/config.json"
configFile, err := os.ReadFile(filepath)
if err != nil {
return err
}
var opt option.Options var opt option.Options
err = opt.UnmarshalJSONContext(globalCtx, configFile) err := opt.UnmarshalJSONContext(globalCtx, sbConfig)
if err != nil { if err != nil {
logger.Error("Unmarshal config err:", err.Error()) logger.Error("Unmarshal config err:", err.Error())
} }
@@ -92,16 +85,6 @@ func (c *Core) Stop() error {
return nil return nil
} }
func (c *Core) Restart() error {
err := c.Stop()
if err != nil {
logger.Error("stop sing-box err:", err.Error())
return err
}
logger.Info("sing-box stopped")
return c.Start()
}
func (c *Core) IsRunning() bool { func (c *Core) IsRunning() bool {
return c.isRunning return c.isRunning
} }
-1
View File
@@ -35,7 +35,6 @@ func (o *Endpoint) UnmarshalJSON(data []byte) error {
func (o Endpoint) MarshalJSON() ([]byte, error) { func (o Endpoint) MarshalJSON() ([]byte, error) {
// Combine fixed fields and dynamic fields into one map // Combine fixed fields and dynamic fields into one map
combined := make(map[string]interface{}) combined := make(map[string]interface{})
combined["id"] = o.Id
combined["type"] = o.Type combined["type"] = o.Type
combined["tag"] = o.Tag combined["tag"] = o.Tag
+3 -2
View File
@@ -1,6 +1,8 @@
package model package model
import "encoding/json" import (
"encoding/json"
)
type Inbound struct { type Inbound struct {
Id uint `json:"id" form:"id" gorm:"primaryKey;autoIncrement"` Id uint `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
@@ -58,7 +60,6 @@ func (i *Inbound) UnmarshalJSON(data []byte) error {
func (i Inbound) MarshalJSON() ([]byte, error) { func (i Inbound) MarshalJSON() ([]byte, error) {
// Combine fixed fields and dynamic fields into one map // Combine fixed fields and dynamic fields into one map
combined := make(map[string]interface{}) combined := make(map[string]interface{})
combined["id"] = i.Id
combined["type"] = i.Type combined["type"] = i.Type
combined["tag"] = i.Tag combined["tag"] = i.Tag
if i.Tls != nil { if i.Tls != nil {
-1
View File
@@ -35,7 +35,6 @@ func (o *Outbound) UnmarshalJSON(data []byte) error {
func (o Outbound) MarshalJSON() ([]byte, error) { func (o Outbound) MarshalJSON() ([]byte, error) {
// Combine fixed fields and dynamic fields into one map // Combine fixed fields and dynamic fields into one map
combined := make(map[string]interface{}) combined := make(map[string]interface{})
combined["id"] = o.Id
combined["type"] = o.Type combined["type"] = o.Type
combined["tag"] = o.Tag combined["tag"] = o.Tag
+2 -2
View File
@@ -12,7 +12,7 @@ require (
github.com/sagernet/sing-dns v0.4.0-beta.1 github.com/sagernet/sing-dns v0.4.0-beta.1
github.com/shirou/gopsutil/v3 v3.24.5 github.com/shirou/gopsutil/v3 v3.24.5
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
gorm.io/driver/sqlite v1.5.6 gorm.io/driver/sqlite v1.5.7
gorm.io/gorm v1.25.12 gorm.io/gorm v1.25.12
) )
@@ -64,7 +64,7 @@ require (
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/mattn/go-sqlite3 v1.14.24 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/socket v0.4.1 // indirect
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa // indirect github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa // indirect
+4
View File
@@ -110,6 +110,8 @@ github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMD
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
@@ -302,6 +304,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE= gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE=
gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
+109 -89
View File
@@ -21,8 +21,10 @@ var (
type ConfigService struct { type ConfigService struct {
ClientService ClientService
TlsService TlsService
InDataService
SettingService SettingService
InboundService
OutboundService
EndpointService
} }
type SingBoxConfig struct { type SingBoxConfig struct {
@@ -31,6 +33,7 @@ type SingBoxConfig struct {
Ntp json.RawMessage `json:"ntp"` Ntp json.RawMessage `json:"ntp"`
Inbounds []json.RawMessage `json:"inbounds"` Inbounds []json.RawMessage `json:"inbounds"`
Outbounds []json.RawMessage `json:"outbounds"` Outbounds []json.RawMessage `json:"outbounds"`
Endpoints []json.RawMessage `json:"endpoints"`
Route json.RawMessage `json:"route"` Route json.RawMessage `json:"route"`
Experimental json.RawMessage `json:"experimental"` Experimental json.RawMessage `json:"experimental"`
} }
@@ -42,47 +45,70 @@ func NewConfigService(core *core.Core) *ConfigService {
func (s *ConfigService) InitConfig() error { func (s *ConfigService) InitConfig() error {
IsSystemd = config.IsSystemd() IsSystemd = config.IsSystemd()
configPath := config.GetBinFolderPath()
data, err := os.ReadFile(configPath + "/config.json")
if err != nil {
if os.IsNotExist(err) {
defaultConfig := []byte(config.GetDefaultConfig())
err = os.MkdirAll(configPath, 01764)
if err != nil {
return err
}
err = os.WriteFile(configPath+"/config.json", defaultConfig, 0764)
if err != nil {
return err
}
data = defaultConfig
} else {
return err
}
}
var singboxConfig SingBoxConfig
err = json.Unmarshal(data, &singboxConfig)
if err != nil {
return err
}
return nil return nil
} }
func (s *ConfigService) GetConfig() (*SingBoxConfig, error) { func (s *ConfigService) GetConfig() (*SingBoxConfig, error) {
configPath := config.GetBinFolderPath() data, err := s.SettingService.GetConfig()
data, err := os.ReadFile(configPath + "/config.json")
if err != nil { if err != nil {
return nil, err return nil, err
} }
singboxConfig := SingBoxConfig{} singboxConfig := SingBoxConfig{}
err = json.Unmarshal(data, &singboxConfig) err = json.Unmarshal([]byte(data), &singboxConfig)
if err != nil {
return nil, err
}
singboxConfig.Inbounds, err = s.InboundService.GetAllConfig(database.GetDB())
if err != nil {
return nil, err
}
singboxConfig.Outbounds, err = s.OutboundService.GetAllConfig(database.GetDB())
if err != nil {
return nil, err
}
singboxConfig.Endpoints, err = s.EndpointService.GetAllConfig(database.GetDB())
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &singboxConfig, nil return &singboxConfig, nil
} }
func (s *ConfigService) StartCore() error {
singboxConfig, err := s.GetConfig()
if err != nil {
return err
}
rawConfig, err := json.MarshalIndent(singboxConfig, "", " ")
if err != nil {
return err
}
err = corePtr.Start(rawConfig)
if err != nil {
logger.Error("start sing-box err:", err.Error())
return err
}
logger.Info("sing-box started")
return nil
}
func (s *ConfigService) RestartCore() error {
err := s.StartCore()
if err != nil {
return err
}
return s.StartCore()
}
func (s *ConfigService) StopCore() error {
err := corePtr.Stop()
if err != nil {
return err
}
logger.Info("sing-box stopped")
return nil
}
func (s *ConfigService) SaveChanges(changes map[string]string, loginUser string) error { func (s *ConfigService) SaveChanges(changes map[string]string, loginUser string) error {
var err error var err error
var clientChanges, tlsChanges, inChanges, settingChanges, configChanges []model.Changes var clientChanges, tlsChanges, inChanges, settingChanges, configChanges []model.Changes
@@ -139,12 +165,12 @@ func (s *ConfigService) SaveChanges(changes map[string]string, loginUser string)
return err return err
} }
} }
if len(inChanges) > 0 { // if len(inChanges) > 0 {
err = s.InDataService.Save(tx, inChanges) // err = s.InDataService.Save(tx, inChanges)
if err != nil { // if err != nil {
return err // return err
} // }
} // }
if len(settingChanges) > 0 { if len(settingChanges) > 0 {
err = s.SettingService.Save(tx, settingChanges) err = s.SettingService.Save(tx, settingChanges)
if err != nil { if err != nil {
@@ -342,7 +368,7 @@ func (s *ConfigService) Save(singboxConfig *SingBoxConfig, needRestart bool) err
} }
if needRestart { if needRestart {
err = corePtr.Restart() err = s.RestartCore()
if err != nil { if err != nil {
return err return err
} }
@@ -353,61 +379,59 @@ func (s *ConfigService) Save(singboxConfig *SingBoxConfig, needRestart bool) err
} }
func (s *ConfigService) DepleteClients() error { func (s *ConfigService) DepleteClients() error {
users, inbounds, err := s.ClientService.DepleteClients() users, inboundIds, err := s.ClientService.DepleteClients()
if err != nil || len(users) == 0 || len(inbounds) == 0 { if err != nil || len(users) == 0 || len(inboundIds) == 0 {
return err return err
} }
singboxConfig, err := s.GetConfig() // inbounds, err := s.InboundService.FromIds(inboundIds)
if err != nil { // if err != nil {
return err // return err
} // }
for inbound_index, inbound := range singboxConfig.Inbounds { // for inbound_index, inbound := range inbounds {
var inboundJson map[string]interface{} // var inboundJson map[string]interface{}
json.Unmarshal(inbound, &inboundJson) // json.Unmarshal(inbound.Options, &inboundJson)
if s.contains(inbounds, inboundJson["tag"].(string)) { // inbound_users, ok := inboundJson["users"].([]interface{})
inbound_users, ok := inboundJson["users"].([]interface{}) // if ok {
if ok { // var updatedUsers []interface{}
var updatedUsers []interface{} // for _, user := range inbound_users {
for _, user := range inbound_users { // userMap, ok := user.(map[string]interface{})
userMap, ok := user.(map[string]interface{}) // if ok {
if ok { // name, exists := userMap["name"].(string)
name, exists := userMap["name"].(string) // if exists && s.contains(users, name) {
if exists && s.contains(users, name) { // // Skip the user exists
// Skip the user exists // continue
continue // }
} // username, exists := userMap["username"].(string)
username, exists := userMap["username"].(string) // if exists && s.contains(users, username) {
if exists && s.contains(users, username) { // // Skip the username exists
// Skip the username exists // continue
continue // }
} // }
} // updatedUsers = append(updatedUsers, user)
updatedUsers = append(updatedUsers, user) // }
} // // Exception for Naive and ShadowTLSv3
// Exception for Naive and ShadowTLSv3 // if len(updatedUsers) == 0 {
if len(updatedUsers) == 0 { // if inboundJson["type"].(string) == "naive" ||
if inboundJson["type"].(string) == "naive" || // (inboundJson["type"].(string) == "shadowtls" &&
(inboundJson["type"].(string) == "shadowtls" && // inboundJson["version"].(float64) == 3) {
inboundJson["version"].(float64) == 3) { // updatedUsers = append(updatedUsers, make(map[string]interface{}))
updatedUsers = append(updatedUsers, make(map[string]interface{})) // }
} // }
}
inboundJson["users"] = updatedUsers // inboundJson["users"] = updatedUsers
} // }
} // modifiedInbound, err := json.MarshalIndent(inboundJson, "", " ")
modifiedInbound, err := json.MarshalIndent(inboundJson, "", " ") // if err != nil {
if err != nil { // return err
return err // }
} // inbounds[inbound_index] = modifiedInbound
singboxConfig.Inbounds[inbound_index] = modifiedInbound // }
}
err = s.Save(singboxConfig, true) // err = s.Save(singboxConfig, true)
if err != nil { // if err != nil {
return err // return err
} // }
return nil return nil
} }
@@ -437,7 +461,3 @@ func (s *ConfigService) GetChanges(actor string, chngKey string, count string) [
} }
return chngs return chngs
} }
func (s *ConfigService) RestartCore() error {
return corePtr.Restart()
}
+48
View File
@@ -0,0 +1,48 @@
package service
import (
"encoding/json"
"s-ui/database"
"s-ui/database/model"
"gorm.io/gorm"
)
type EndpointService struct{}
func (o *EndpointService) GetAll() ([]*model.Endpoint, error) {
db := database.GetDB()
endpoints := []*model.Endpoint{}
err := db.Model(model.Endpoint{}).Scan(&endpoints).Error
if err != nil {
return nil, err
}
return endpoints, nil
}
func (o *EndpointService) Get(id uint) (*model.Endpoint, error) {
db := database.GetDB()
endpoint := &model.Endpoint{}
err := db.First(endpoint, id).Error
if err != nil {
return nil, err
}
return endpoint, nil
}
func (o *EndpointService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
var endpointsJson []json.RawMessage
var endpoints []*model.Endpoint
err := db.Model(model.Endpoint{}).Scan(&endpoints).Error
if err != nil {
return nil, err
}
for _, endpoint := range endpoints {
endpointJson, err := endpoint.MarshalJSON()
if err != nil {
return nil, err
}
endpointsJson = append(endpointsJson, endpointJson)
}
return endpointsJson, nil
}
+52 -4
View File
@@ -1,6 +1,7 @@
package service package service
import ( import (
"encoding/json"
"s-ui/database" "s-ui/database"
"s-ui/database/model" "s-ui/database/model"
@@ -9,14 +10,14 @@ import (
type InboundService struct{} type InboundService struct{}
func (s *InboundService) GetAll() ([]model.Inbound, error) { func (s *InboundService) GetAll() (*[]map[string]interface{}, error) {
db := database.GetDB() db := database.GetDB()
inbounds := []model.Inbound{} inbounds := []map[string]interface{}{}
err := db.Model(model.Inbound{}).Scan(&inbounds).Error err := db.Model(model.Inbound{}).Select("id, tag, type, address, port, tls_id , count(users) as ucount").Scan(&inbounds).Error
if err != nil { if err != nil {
return nil, err return nil, err
} }
return inbounds, nil return &inbounds, nil
} }
func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error) { func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error) {
@@ -32,3 +33,50 @@ func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error) {
func (s *InboundService) Save(db *gorm.DB, inbounds []*model.Inbound) error { func (s *InboundService) Save(db *gorm.DB, inbounds []*model.Inbound) error {
return db.Save(inbounds).Error return db.Save(inbounds).Error
} }
func (s *InboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
var inboundsJson []json.RawMessage
var inbounds []*model.Inbound
err := db.Model(model.Inbound{}).Preload("Tls").Find(&inbounds).Error
if err != nil {
return nil, err
}
for _, inbound := range inbounds {
inboundJson, err := inbound.MarshalJSON()
if err != nil {
return nil, err
}
switch inbound.Type {
case "mixed", "socks", "http", "shadowsocks", "vmess", "trojan", "naive", "hysteria", "shadowtls", "tuic", "hysteria2", "vless":
inboundJson, err = s.addUsers(db, inboundJson, inbound.Id, inbound.Type)
if err != nil {
return nil, err
}
}
inboundsJson = append(inboundsJson, inboundJson)
}
return inboundsJson, nil
}
func (s *InboundService) addUsers(db *gorm.DB, inboundJson []byte, inboundId uint, inboundType string) ([]byte, error) {
var inbound map[string]interface{}
err := json.Unmarshal(inboundJson, &inbound)
if err != nil {
return nil, err
}
var users []string
err = db.Raw(`SELECT json_extract(clients.config, ?)
FROM clients, json_each(clients.inbounds) as je
WHERE clients.enable = true AND je.value = ?;`,
"$."+inboundType, inboundId).Scan(&users).Error
if err != nil {
return nil, err
}
var usersJson []json.RawMessage
for _, user := range users {
usersJson = append(usersJson, json.RawMessage(user))
}
inbound["users"] = usersJson
return json.Marshal(inbound)
}
+48
View File
@@ -0,0 +1,48 @@
package service
import (
"encoding/json"
"s-ui/database"
"s-ui/database/model"
"gorm.io/gorm"
)
type OutboundService struct{}
func (o *OutboundService) GetAll() ([]*model.Outbound, error) {
db := database.GetDB()
outbounds := []*model.Outbound{}
err := db.Model(model.Outbound{}).Scan(&outbounds).Error
if err != nil {
return nil, err
}
return outbounds, nil
}
func (o *OutboundService) Get(id uint) (*model.Outbound, error) {
db := database.GetDB()
outbound := &model.Outbound{}
err := db.First(outbound, id).Error
if err != nil {
return nil, err
}
return outbound, nil
}
func (o *OutboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
var outboundsJson []json.RawMessage
var outbounds []*model.Outbound
err := db.Model(model.Outbound{}).Scan(&outbounds).Error
if err != nil {
return nil, err
}
for _, outbound := range outbounds {
outboundJson, err := outbound.MarshalJSON()
if err != nil {
return nil, err
}
outboundsJson = append(outboundsJson, outboundJson)
}
return outboundsJson, nil
}