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
+109 -89
View File
@@ -21,8 +21,10 @@ var (
type ConfigService struct {
ClientService
TlsService
InDataService
SettingService
InboundService
OutboundService
EndpointService
}
type SingBoxConfig struct {
@@ -31,6 +33,7 @@ type SingBoxConfig struct {
Ntp json.RawMessage `json:"ntp"`
Inbounds []json.RawMessage `json:"inbounds"`
Outbounds []json.RawMessage `json:"outbounds"`
Endpoints []json.RawMessage `json:"endpoints"`
Route json.RawMessage `json:"route"`
Experimental json.RawMessage `json:"experimental"`
}
@@ -42,47 +45,70 @@ func NewConfigService(core *core.Core) *ConfigService {
func (s *ConfigService) InitConfig() error {
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
}
func (s *ConfigService) GetConfig() (*SingBoxConfig, error) {
configPath := config.GetBinFolderPath()
data, err := os.ReadFile(configPath + "/config.json")
data, err := s.SettingService.GetConfig()
if err != nil {
return nil, err
}
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 {
return nil, err
}
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 {
var err error
var clientChanges, tlsChanges, inChanges, settingChanges, configChanges []model.Changes
@@ -139,12 +165,12 @@ func (s *ConfigService) SaveChanges(changes map[string]string, loginUser string)
return err
}
}
if len(inChanges) > 0 {
err = s.InDataService.Save(tx, inChanges)
if err != nil {
return err
}
}
// if len(inChanges) > 0 {
// err = s.InDataService.Save(tx, inChanges)
// if err != nil {
// return err
// }
// }
if len(settingChanges) > 0 {
err = s.SettingService.Save(tx, settingChanges)
if err != nil {
@@ -342,7 +368,7 @@ func (s *ConfigService) Save(singboxConfig *SingBoxConfig, needRestart bool) err
}
if needRestart {
err = corePtr.Restart()
err = s.RestartCore()
if err != nil {
return err
}
@@ -353,61 +379,59 @@ func (s *ConfigService) Save(singboxConfig *SingBoxConfig, needRestart bool) err
}
func (s *ConfigService) DepleteClients() error {
users, inbounds, err := s.ClientService.DepleteClients()
if err != nil || len(users) == 0 || len(inbounds) == 0 {
users, inboundIds, err := s.ClientService.DepleteClients()
if err != nil || len(users) == 0 || len(inboundIds) == 0 {
return err
}
singboxConfig, err := s.GetConfig()
if err != nil {
return err
}
for inbound_index, inbound := range singboxConfig.Inbounds {
var inboundJson map[string]interface{}
json.Unmarshal(inbound, &inboundJson)
if s.contains(inbounds, inboundJson["tag"].(string)) {
inbound_users, ok := inboundJson["users"].([]interface{})
if ok {
var updatedUsers []interface{}
for _, user := range inbound_users {
userMap, ok := user.(map[string]interface{})
if ok {
name, exists := userMap["name"].(string)
if exists && s.contains(users, name) {
// Skip the user exists
continue
}
username, exists := userMap["username"].(string)
if exists && s.contains(users, username) {
// Skip the username exists
continue
}
}
updatedUsers = append(updatedUsers, user)
}
// Exception for Naive and ShadowTLSv3
if len(updatedUsers) == 0 {
if inboundJson["type"].(string) == "naive" ||
(inboundJson["type"].(string) == "shadowtls" &&
inboundJson["version"].(float64) == 3) {
updatedUsers = append(updatedUsers, make(map[string]interface{}))
}
}
// inbounds, err := s.InboundService.FromIds(inboundIds)
// if err != nil {
// return err
// }
// for inbound_index, inbound := range inbounds {
// var inboundJson map[string]interface{}
// json.Unmarshal(inbound.Options, &inboundJson)
// inbound_users, ok := inboundJson["users"].([]interface{})
// if ok {
// var updatedUsers []interface{}
// for _, user := range inbound_users {
// userMap, ok := user.(map[string]interface{})
// if ok {
// name, exists := userMap["name"].(string)
// if exists && s.contains(users, name) {
// // Skip the user exists
// continue
// }
// username, exists := userMap["username"].(string)
// if exists && s.contains(users, username) {
// // Skip the username exists
// continue
// }
// }
// updatedUsers = append(updatedUsers, user)
// }
// // Exception for Naive and ShadowTLSv3
// if len(updatedUsers) == 0 {
// if inboundJson["type"].(string) == "naive" ||
// (inboundJson["type"].(string) == "shadowtls" &&
// inboundJson["version"].(float64) == 3) {
// updatedUsers = append(updatedUsers, make(map[string]interface{}))
// }
// }
inboundJson["users"] = updatedUsers
}
}
modifiedInbound, err := json.MarshalIndent(inboundJson, "", " ")
if err != nil {
return err
}
singboxConfig.Inbounds[inbound_index] = modifiedInbound
}
// inboundJson["users"] = updatedUsers
// }
// modifiedInbound, err := json.MarshalIndent(inboundJson, "", " ")
// if err != nil {
// return err
// }
// inbounds[inbound_index] = modifiedInbound
// }
err = s.Save(singboxConfig, true)
if err != nil {
return err
}
// err = s.Save(singboxConfig, true)
// if err != nil {
// return err
// }
return nil
}
@@ -437,7 +461,3 @@ func (s *ConfigService) GetChanges(actor string, chngKey string, count string) [
}
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
import (
"encoding/json"
"s-ui/database"
"s-ui/database/model"
@@ -9,14 +10,14 @@ import (
type InboundService struct{}
func (s *InboundService) GetAll() ([]model.Inbound, error) {
func (s *InboundService) GetAll() (*[]map[string]interface{}, error) {
db := database.GetDB()
inbounds := []model.Inbound{}
err := db.Model(model.Inbound{}).Scan(&inbounds).Error
inbounds := []map[string]interface{}{}
err := db.Model(model.Inbound{}).Select("id, tag, type, address, port, tls_id , count(users) as ucount").Scan(&inbounds).Error
if err != nil {
return nil, err
}
return inbounds, nil
return &inbounds, nil
}
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 {
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
}