all adjustments
This commit is contained in:
+109
-23
@@ -11,6 +11,7 @@ import (
|
||||
)
|
||||
|
||||
type ClientService struct {
|
||||
InboundService
|
||||
}
|
||||
|
||||
func (s *ClientService) GetAll() ([]model.Client, error) {
|
||||
@@ -23,48 +24,117 @@ func (s *ClientService) GetAll() ([]model.Client, error) {
|
||||
return clients, nil
|
||||
}
|
||||
|
||||
func (s *ClientService) Save(tx *gorm.DB, changes []model.Changes) error {
|
||||
func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage) ([]uint, error) {
|
||||
var err error
|
||||
for _, change := range changes {
|
||||
client := model.Client{}
|
||||
err = json.Unmarshal(change.Obj, &client)
|
||||
var inboundIds []uint
|
||||
|
||||
switch act {
|
||||
case "new", "edit":
|
||||
var client model.Client
|
||||
err = json.Unmarshal(data, &client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(client.Inbounds, &inboundIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = tx.Save(&client).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "del":
|
||||
var id uint
|
||||
err = json.Unmarshal(data, &id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var client model.Client
|
||||
err = tx.Where("id = ?", id).First(&client).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(client.Inbounds, &inboundIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = tx.Where("id = ?", id).Delete(model.Client{}).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return inboundIds, nil
|
||||
}
|
||||
|
||||
func (s *ClientService) UpdateLinks(tx *gorm.DB, links json.RawMessage) error {
|
||||
var userLinks []interface{}
|
||||
err := json.Unmarshal(links, &userLinks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, userLink := range userLinks {
|
||||
userLinkData, _ := userLink.(map[string]interface{})
|
||||
userId, _ := userLinkData["id"].(float64)
|
||||
links, err := json.MarshalIndent(userLinkData["links"], "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch change.Action {
|
||||
case "new":
|
||||
err = tx.Create(&client).Error
|
||||
case "del":
|
||||
err = tx.Where("id = ?", change.Index).Delete(model.Client{}).Error
|
||||
default:
|
||||
err = tx.Save(client).Error
|
||||
if inbounds, ok := userLinkData["inbounds"]; ok {
|
||||
inbounds, err := json.MarshalIndent(inbounds, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Model(model.Client{}).Where("id = ?", uint(userId)).Update("inbounds", inbounds).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = tx.Model(model.Client{}).Where("id = ?", uint(userId)).Update("links", links).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ClientService) DepleteClients() ([]string, []string, error) {
|
||||
func (s *ClientService) DepleteClients() error {
|
||||
var err error
|
||||
var clients []model.Client
|
||||
var changes []model.Changes
|
||||
var users []string
|
||||
var inboundIds []uint
|
||||
|
||||
now := time.Now().Unix()
|
||||
db := database.GetDB()
|
||||
err = db.Model(model.Client{}).Where("enable = true AND ((volume >0 AND up+down > volume) OR (expiry > 0 AND expiry < ?))", now).Scan(&clients).Error
|
||||
|
||||
tx := db.Begin()
|
||||
defer func() {
|
||||
if err == nil {
|
||||
tx.Commit()
|
||||
if len(inboundIds) > 0 && corePtr.IsRunning() {
|
||||
err1 := s.InboundService.RestartInbounds(tx, inboundIds)
|
||||
if err1 != nil {
|
||||
logger.Error("unable to restart inbounds: ", err1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
err = tx.Model(model.Client{}).Where("enable = true AND ((volume >0 AND up+down > volume) OR (expiry > 0 AND expiry < ?))", now).Scan(&clients).Error
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
dt := time.Now().Unix()
|
||||
var users, inbounds []string
|
||||
for _, client := range clients {
|
||||
logger.Debug("Client ", client.Name, " is going to be disabled")
|
||||
users = append(users, client.Name)
|
||||
var userInbounds []string
|
||||
var userInbounds []uint
|
||||
json.Unmarshal(client.Inbounds, &userInbounds)
|
||||
inbounds = append(inbounds, userInbounds...)
|
||||
inboundIds = s.uniqueAppendInboundIds(inboundIds, userInbounds)
|
||||
changes = append(changes, model.Changes{
|
||||
DateTime: dt,
|
||||
Actor: "DepleteJob",
|
||||
@@ -76,16 +146,32 @@ func (s *ClientService) DepleteClients() ([]string, []string, error) {
|
||||
|
||||
// Save changes
|
||||
if len(changes) > 0 {
|
||||
err = db.Model(model.Client{}).Where("enable = true AND ((volume >0 AND up+down > volume) OR (expiry > 0 AND expiry < ?))", now).Update("enable", false).Error
|
||||
err = tx.Model(model.Client{}).Where("enable = true AND ((volume >0 AND up+down > volume) OR (expiry > 0 AND expiry < ?))", now).Update("enable", false).Error
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return err
|
||||
}
|
||||
err = db.Model(model.Changes{}).Create(&changes).Error
|
||||
err = tx.Model(model.Changes{}).Create(&changes).Error
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return err
|
||||
}
|
||||
LastUpdate = dt
|
||||
}
|
||||
|
||||
return users, inbounds, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// avoid duplicate inboundIds
|
||||
func (s *ClientService) uniqueAppendInboundIds(a []uint, b []uint) []uint {
|
||||
m := make(map[uint]bool)
|
||||
for _, v := range a {
|
||||
m[v] = true
|
||||
}
|
||||
for _, v := range b {
|
||||
m[v] = true
|
||||
}
|
||||
var res []uint
|
||||
for k := range m {
|
||||
res = append(res, k)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
+72
-297
@@ -2,12 +2,12 @@ package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"s-ui/config"
|
||||
"s-ui/core"
|
||||
"s-ui/database"
|
||||
"s-ui/database/model"
|
||||
"s-ui/logger"
|
||||
"s-ui/util/common"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
@@ -48,10 +48,13 @@ func (s *ConfigService) InitConfig() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ConfigService) GetConfig() (*SingBoxConfig, error) {
|
||||
data, err := s.SettingService.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (s *ConfigService) GetConfig(data string) (*SingBoxConfig, error) {
|
||||
var err error
|
||||
if len(data) == 0 {
|
||||
data, err = s.SettingService.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
singboxConfig := SingBoxConfig{}
|
||||
err = json.Unmarshal([]byte(data), &singboxConfig)
|
||||
@@ -74,8 +77,11 @@ func (s *ConfigService) GetConfig() (*SingBoxConfig, error) {
|
||||
return &singboxConfig, nil
|
||||
}
|
||||
|
||||
func (s *ConfigService) StartCore() error {
|
||||
singboxConfig, err := s.GetConfig()
|
||||
func (s *ConfigService) StartCore(defaultConfig string) error {
|
||||
if corePtr.IsRunning() {
|
||||
return nil
|
||||
}
|
||||
singboxConfig, err := s.GetConfig(defaultConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -93,11 +99,19 @@ func (s *ConfigService) StartCore() error {
|
||||
}
|
||||
|
||||
func (s *ConfigService) RestartCore() error {
|
||||
err := s.StartCore()
|
||||
err := s.StopCore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.StartCore()
|
||||
return s.StartCore("")
|
||||
}
|
||||
|
||||
func (s *ConfigService) restartCoreWithConfig(config json.RawMessage) error {
|
||||
err := s.StopCore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.StartCore(string(config))
|
||||
}
|
||||
|
||||
func (s *ConfigService) StopCore() error {
|
||||
@@ -109,220 +123,80 @@ func (s *ConfigService) StopCore() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ConfigService) SaveChanges(changes map[string]string, loginUser string) error {
|
||||
func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userLinks json.RawMessage, outJsons json.RawMessage, loginUser string) error {
|
||||
var err error
|
||||
var clientChanges, tlsChanges, inChanges, settingChanges, configChanges []model.Changes
|
||||
if _, ok := changes["clients"]; ok {
|
||||
err = json.Unmarshal([]byte(changes["clients"]), &clientChanges)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, ok := changes["tls"]; ok {
|
||||
err = json.Unmarshal([]byte(changes["tls"]), &tlsChanges)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, ok := changes["inData"]; ok {
|
||||
err = json.Unmarshal([]byte(changes["inData"]), &inChanges)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, ok := changes["settings"]; ok {
|
||||
err = json.Unmarshal([]byte(changes["settings"]), &settingChanges)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, ok := changes["config"]; ok {
|
||||
err = json.Unmarshal([]byte(changes["config"]), &configChanges)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var inboundIds []uint
|
||||
|
||||
db := database.GetDB()
|
||||
tx := db.Begin()
|
||||
defer func() {
|
||||
if err == nil {
|
||||
tx.Commit()
|
||||
if len(inboundIds) > 0 && corePtr.IsRunning() {
|
||||
err1 := s.InboundService.RestartInbounds(tx, inboundIds)
|
||||
if err1 != nil {
|
||||
logger.Error("unable to restart inbounds: ", err1)
|
||||
}
|
||||
}
|
||||
// Try to start core if it is not running
|
||||
if !corePtr.IsRunning() {
|
||||
s.StartCore("")
|
||||
}
|
||||
} else {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
if len(clientChanges) > 0 {
|
||||
err = s.ClientService.Save(tx, clientChanges)
|
||||
switch obj {
|
||||
case "clients":
|
||||
inboundIds, err = s.ClientService.Save(tx, act, data)
|
||||
case "tls":
|
||||
inboundIds, err = s.TlsService.Save(tx, act, data)
|
||||
case "inbounds":
|
||||
err = s.InboundService.Save(tx, act, data)
|
||||
case "outbounds":
|
||||
err = s.OutboundService.Save(tx, act, data)
|
||||
case "endpoints":
|
||||
err = s.EndpointService.Save(tx, act, data)
|
||||
case "config":
|
||||
err = s.SettingService.SaveConfig(tx, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.restartCoreWithConfig(data)
|
||||
default:
|
||||
return common.NewError("unknown object: ", obj)
|
||||
}
|
||||
if len(tlsChanges) > 0 {
|
||||
err = s.TlsService.Save(tx, tlsChanges)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
needRestart := false
|
||||
if len(configChanges) > 0 {
|
||||
singboxConfig, err := s.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newConfig := *singboxConfig
|
||||
for _, change := range configChanges {
|
||||
rawObject := change.Obj
|
||||
switch change.Key {
|
||||
case "all":
|
||||
err = json.Unmarshal(rawObject, &newConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
needRestart = true
|
||||
case "log":
|
||||
newConfig.Log = rawObject
|
||||
needRestart = true
|
||||
case "dns":
|
||||
newConfig.Dns = rawObject
|
||||
needRestart = true
|
||||
case "ntp":
|
||||
newConfig.Ntp = rawObject
|
||||
needRestart = true
|
||||
case "route":
|
||||
newConfig.Route = rawObject
|
||||
needRestart = true
|
||||
case "experimental":
|
||||
newConfig.Experimental = rawObject
|
||||
needRestart = true
|
||||
case "inbounds":
|
||||
if change.Action == "edit" {
|
||||
var object map[string]interface{}
|
||||
err = json.Unmarshal(newConfig.Inbounds[change.Index], &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tag, ok := object["tag"].(string); ok {
|
||||
err = corePtr.RemoveInbound(tag)
|
||||
if err == nil {
|
||||
err = corePtr.AddInbound(rawObject)
|
||||
if err != nil {
|
||||
needRestart = true
|
||||
}
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
newConfig.Inbounds[change.Index] = rawObject
|
||||
} else if change.Action == "del" {
|
||||
var object map[string]interface{}
|
||||
err = json.Unmarshal(newConfig.Inbounds[change.Index], &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tag, ok := object["tag"].(string); ok {
|
||||
err = corePtr.RemoveInbound(tag)
|
||||
if err != nil {
|
||||
needRestart = true
|
||||
}
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
newConfig.Inbounds = append(newConfig.Inbounds[:change.Index], newConfig.Inbounds[change.Index+1:]...)
|
||||
} else {
|
||||
newConfig.Inbounds = append(newConfig.Inbounds, rawObject)
|
||||
err = corePtr.AddInbound(rawObject)
|
||||
if err != nil {
|
||||
logger.Debug(err)
|
||||
needRestart = true
|
||||
}
|
||||
}
|
||||
case "outbounds":
|
||||
if change.Action == "edit" {
|
||||
var object map[string]interface{}
|
||||
err = json.Unmarshal(newConfig.Outbounds[change.Index], &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tag, ok := object["tag"].(string); ok {
|
||||
err = corePtr.RemoveOutbound(tag)
|
||||
if err == nil {
|
||||
err = corePtr.AddOutbound(rawObject)
|
||||
if err != nil {
|
||||
needRestart = true
|
||||
}
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
newConfig.Outbounds[change.Index] = rawObject
|
||||
} else if change.Action == "del" {
|
||||
var object map[string]interface{}
|
||||
err = json.Unmarshal(newConfig.Outbounds[change.Index], &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tag, ok := object["tag"].(string); ok {
|
||||
err = corePtr.RemoveOutbound(tag)
|
||||
if err != nil {
|
||||
needRestart = true
|
||||
}
|
||||
} else {
|
||||
needRestart = true
|
||||
}
|
||||
newConfig.Outbounds = append(newConfig.Outbounds[:change.Index], newConfig.Outbounds[change.Index+1:]...)
|
||||
} else {
|
||||
err = corePtr.AddOutbound(rawObject)
|
||||
if err != nil {
|
||||
logger.Debug(err)
|
||||
needRestart = true
|
||||
}
|
||||
newConfig.Outbounds = append(newConfig.Outbounds, rawObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = s.Save(&newConfig, needRestart)
|
||||
if len(userLinks) > 0 {
|
||||
err = s.ClientService.UpdateLinks(tx, userLinks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(outJsons) > 0 {
|
||||
err = s.InboundService.UpdateOutJsons(tx, outJsons)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Log changes
|
||||
dt := time.Now().Unix()
|
||||
allChanges := append(clientChanges, settingChanges...)
|
||||
allChanges = append(allChanges, configChanges...)
|
||||
allChanges = append(allChanges, tlsChanges...)
|
||||
allChanges = append(allChanges, inChanges...)
|
||||
if len(allChanges) > 0 {
|
||||
for index := range allChanges {
|
||||
allChanges[index].DateTime = dt
|
||||
allChanges[index].Actor = loginUser
|
||||
}
|
||||
err = tx.Model(model.Changes{}).Create(&allChanges).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Create(&model.Changes{
|
||||
DateTime: dt,
|
||||
Actor: loginUser,
|
||||
Key: obj,
|
||||
Action: act,
|
||||
Obj: data,
|
||||
}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
LastUpdate = dt
|
||||
LastUpdate = time.Now().Unix()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -345,105 +219,6 @@ func (s *ConfigService) CheckChanges(lu string) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConfigService) Save(singboxConfig *SingBoxConfig, needRestart bool) error {
|
||||
configPath := config.GetBinFolderPath()
|
||||
_, err := os.Stat(configPath + "/config.json")
|
||||
if os.IsNotExist(err) {
|
||||
err = os.MkdirAll(configPath, 01764)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(singboxConfig, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.WriteFile(configPath+"/config.json", data, 0764)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if needRestart {
|
||||
err = s.RestartCore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// s.Controller.Restart()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ConfigService) DepleteClients() error {
|
||||
users, inboundIds, err := s.ClientService.DepleteClients()
|
||||
if err != nil || len(users) == 0 || len(inboundIds) == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
// 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
|
||||
// }
|
||||
// inbounds[inbound_index] = modifiedInbound
|
||||
// }
|
||||
|
||||
// err = s.Save(singboxConfig, true)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ConfigService) contains(slice []string, item string) bool {
|
||||
for _, str := range slice {
|
||||
if str == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *ConfigService) GetChanges(actor string, chngKey string, count string) []model.Changes {
|
||||
c, _ := strconv.Atoi(count)
|
||||
whereString := "`id`>0"
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"s-ui/database"
|
||||
"s-ui/database/model"
|
||||
|
||||
@@ -10,24 +11,32 @@ import (
|
||||
|
||||
type EndpointService struct{}
|
||||
|
||||
func (o *EndpointService) GetAll() ([]*model.Endpoint, error) {
|
||||
func (o *EndpointService) GetAll() (*[]map[string]interface{}, 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
|
||||
var data []map[string]interface{}
|
||||
for _, endpoint := range endpoints {
|
||||
epData := map[string]interface{}{
|
||||
"id": endpoint.Id,
|
||||
"type": endpoint.Type,
|
||||
"tag": endpoint.Tag,
|
||||
}
|
||||
if endpoint.Options != nil {
|
||||
var restFields map[string]json.RawMessage
|
||||
if err := json.Unmarshal(endpoint.Options, &restFields); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range restFields {
|
||||
epData[k] = v
|
||||
}
|
||||
}
|
||||
data = append(data, epData)
|
||||
}
|
||||
return endpoint, nil
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func (o *EndpointService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
|
||||
@@ -46,3 +55,55 @@ func (o *EndpointService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
|
||||
}
|
||||
return endpointsJson, nil
|
||||
}
|
||||
|
||||
func (s *EndpointService) Save(tx *gorm.DB, action string, data json.RawMessage) error {
|
||||
var err error
|
||||
|
||||
switch action {
|
||||
case "new", "edit":
|
||||
var endpoint model.Endpoint
|
||||
err = endpoint.UnmarshalJSON(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if corePtr.IsRunning() {
|
||||
configData, err := endpoint.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if action == "edit" {
|
||||
err = corePtr.RemoveEndpoint(endpoint.Tag)
|
||||
if err != nil && err != os.ErrInvalid {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = corePtr.AddEndpoint(configData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Save(&endpoint).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "del":
|
||||
var tag string
|
||||
err = json.Unmarshal(data, &tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if corePtr.IsRunning() {
|
||||
err = corePtr.RemoveEndpoint(tag)
|
||||
if err != nil && err != os.ErrInvalid {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = tx.Where("tag = ?", tag).Delete(model.Endpoint{}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+174
-12
@@ -2,22 +2,67 @@ package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"s-ui/database"
|
||||
"s-ui/database/model"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type InboundService struct{}
|
||||
|
||||
func (s *InboundService) GetAll() (*[]map[string]interface{}, error) {
|
||||
func (s *InboundService) Get(ids string) (*[]map[string]interface{}, error) {
|
||||
if ids == "" {
|
||||
return s.GetAll()
|
||||
}
|
||||
return s.getById(ids)
|
||||
}
|
||||
|
||||
func (s *InboundService) getById(ids string) (*[]map[string]interface{}, error) {
|
||||
var inbound []model.Inbound
|
||||
var result []map[string]interface{}
|
||||
db := database.GetDB()
|
||||
inbounds := []map[string]interface{}{}
|
||||
err := db.Model(model.Inbound{}).Select("id, tag, type, address, port, tls_id , count(users) as ucount").Scan(&inbounds).Error
|
||||
err := db.Model(model.Inbound{}).Where("id in ?", strings.Split(ids, ",")).Scan(&inbound).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &inbounds, nil
|
||||
for _, inb := range inbound {
|
||||
inbData, err := inb.MarshalFull()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, *inbData)
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (s *InboundService) GetAll() (*[]map[string]interface{}, error) {
|
||||
db := database.GetDB()
|
||||
inbounds := []model.Inbound{}
|
||||
err := db.Model(model.Inbound{}).Scan(&inbounds).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data []map[string]interface{}
|
||||
for _, inbound := range inbounds {
|
||||
inbData := map[string]interface{}{
|
||||
"id": inbound.Id,
|
||||
"type": inbound.Type,
|
||||
"tag": inbound.Tag,
|
||||
"tls_id": inbound.TlsId,
|
||||
}
|
||||
if inbound.Options != nil {
|
||||
var restFields map[string]json.RawMessage
|
||||
if err := json.Unmarshal(inbound.Options, &restFields); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inbData["listen"] = restFields["listen"]
|
||||
inbData["listen_port"] = restFields["listen_port"]
|
||||
}
|
||||
data = append(data, inbData)
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error) {
|
||||
@@ -30,8 +75,91 @@ func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error) {
|
||||
return inbounds, nil
|
||||
}
|
||||
|
||||
func (s *InboundService) Save(db *gorm.DB, inbounds []*model.Inbound) error {
|
||||
return db.Save(inbounds).Error
|
||||
func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage) error {
|
||||
var err error
|
||||
|
||||
switch act {
|
||||
case "new", "edit":
|
||||
var inbound model.Inbound
|
||||
err = inbound.UnmarshalJSON(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if corePtr.IsRunning() {
|
||||
if act == "edit" {
|
||||
err = corePtr.RemoveInbound(inbound.Tag)
|
||||
if err != nil && err != os.ErrInvalid {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if inbound.TlsId > 0 {
|
||||
err = tx.Model(model.Tls{}).Where("id = ?", inbound.TlsId).Find(&inbound.Tls).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
inboundConfig, err := inbound.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inboundConfig, err = s.addUsers(tx, inboundConfig, inbound.Id, inbound.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = corePtr.AddInbound(inboundConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Save(&inbound).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "del":
|
||||
var tag string
|
||||
err = json.Unmarshal(data, &tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if corePtr.IsRunning() {
|
||||
err = corePtr.RemoveInbound(tag)
|
||||
if err != nil && err != os.ErrInvalid {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = tx.Where("tag = ?", tag).Delete(model.Inbound{}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *InboundService) UpdateOutJsons(tx *gorm.DB, data json.RawMessage) error {
|
||||
var outJsons []interface{}
|
||||
err := json.Unmarshal(data, &outJsons)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, outJson := range outJsons {
|
||||
outJsonData := outJson.(map[string]interface{})
|
||||
tag := outJsonData["tag"].(string)
|
||||
outJson, err := json.MarshalIndent(outJsonData["out_json"], "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Model(model.Inbound{}).Where("tag = ?", tag).Update("out_json", outJson).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *InboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
|
||||
@@ -46,12 +174,9 @@ func (s *InboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
|
||||
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
|
||||
}
|
||||
inboundJson, err = s.addUsers(db, inboundJson, inbound.Id, inbound.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inboundsJson = append(inboundsJson, inboundJson)
|
||||
}
|
||||
@@ -59,11 +184,24 @@ func (s *InboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
|
||||
}
|
||||
|
||||
func (s *InboundService) addUsers(db *gorm.DB, inboundJson []byte, inboundId uint, inboundType string) ([]byte, error) {
|
||||
switch inboundType {
|
||||
case "mixed", "socks", "http", "shadowsocks", "vmess", "trojan", "naive", "hysteria", "shadowtls", "tuic", "hysteria2", "vless":
|
||||
break
|
||||
default:
|
||||
return inboundJson, nil
|
||||
}
|
||||
|
||||
var inbound map[string]interface{}
|
||||
err := json.Unmarshal(inboundJson, &inbound)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if inboundType == "shadowsocks" {
|
||||
method, _ := inbound["method"].(string)
|
||||
if method == "2022-blake3-aes-128-gcm" {
|
||||
inboundType = "shadowsocks16"
|
||||
}
|
||||
}
|
||||
var users []string
|
||||
err = db.Raw(`SELECT json_extract(clients.config, ?)
|
||||
FROM clients, json_each(clients.inbounds) as je
|
||||
@@ -80,3 +218,27 @@ func (s *InboundService) addUsers(db *gorm.DB, inboundJson []byte, inboundId uin
|
||||
inbound["users"] = usersJson
|
||||
return json.Marshal(inbound)
|
||||
}
|
||||
|
||||
func (s *InboundService) RestartInbounds(tx *gorm.DB, ids []uint) error {
|
||||
var inbounds []*model.Inbound
|
||||
err := tx.Model(model.Inbound{}).Preload("Tls").Where("id in ?", ids).Find(&inbounds).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, inbound := range inbounds {
|
||||
err = corePtr.RemoveInbound(inbound.Tag)
|
||||
if err != nil && err != os.ErrInvalid {
|
||||
return err
|
||||
}
|
||||
inboundConfig, err := inbound.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
inboundConfig, err = s.addUsers(tx, inboundConfig, inbound.Id, inbound.Type)
|
||||
err = corePtr.AddInbound(inboundConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"s-ui/database"
|
||||
"s-ui/database/model"
|
||||
|
||||
@@ -10,24 +11,32 @@ import (
|
||||
|
||||
type OutboundService struct{}
|
||||
|
||||
func (o *OutboundService) GetAll() ([]*model.Outbound, error) {
|
||||
func (o *OutboundService) GetAll() (*[]map[string]interface{}, 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
|
||||
var data []map[string]interface{}
|
||||
for _, outbound := range outbounds {
|
||||
outData := map[string]interface{}{
|
||||
"id": outbound.Id,
|
||||
"type": outbound.Type,
|
||||
"tag": outbound.Tag,
|
||||
}
|
||||
if outbound.Options != nil {
|
||||
var restFields map[string]json.RawMessage
|
||||
if err := json.Unmarshal(outbound.Options, &restFields); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range restFields {
|
||||
outData[k] = v
|
||||
}
|
||||
}
|
||||
data = append(data, outData)
|
||||
}
|
||||
return outbound, nil
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func (o *OutboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
|
||||
@@ -46,3 +55,55 @@ func (o *OutboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
|
||||
}
|
||||
return outboundsJson, nil
|
||||
}
|
||||
|
||||
func (s *OutboundService) Save(tx *gorm.DB, action string, data json.RawMessage) error {
|
||||
var err error
|
||||
|
||||
switch action {
|
||||
case "new", "edit":
|
||||
var outbound model.Outbound
|
||||
err = outbound.UnmarshalJSON(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if corePtr.IsRunning() {
|
||||
configData, err := outbound.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if action == "edit" {
|
||||
err = corePtr.RemoveOutbound(outbound.Tag)
|
||||
if err != nil && err != os.ErrInvalid {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = corePtr.AddOutbound(configData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Save(&outbound).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "del":
|
||||
var tag string
|
||||
err = json.Unmarshal(data, &tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if corePtr.IsRunning() {
|
||||
err = corePtr.RemoveOutbound(tag)
|
||||
if err != nil && err != os.ErrInvalid {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = tx.Where("tag = ?", tag).Delete(model.Outbound{}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -343,6 +343,14 @@ func (s *SettingService) SetConfig(config string) error {
|
||||
return s.setString("config", config)
|
||||
}
|
||||
|
||||
func (s *SettingService) SaveConfig(tx *gorm.DB, config json.RawMessage) error {
|
||||
configs, err := json.MarshalIndent(config, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(model.Setting{}).Where("key = ?", "config").Update("value", string(configs)).Error
|
||||
}
|
||||
|
||||
func (s *SettingService) Save(tx *gorm.DB, changes []model.Changes) error {
|
||||
var err error
|
||||
for _, change := range changes {
|
||||
|
||||
@@ -74,7 +74,7 @@ func (s *StatsService) SaveStats() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *StatsService) GetStats(resorce string, tag string, limit int) ([]model.Stats, error) {
|
||||
func (s *StatsService) GetStats(resource string, tag string, limit int) ([]model.Stats, error) {
|
||||
var err error
|
||||
var result []model.Stats
|
||||
|
||||
@@ -82,7 +82,11 @@ func (s *StatsService) GetStats(resorce string, tag string, limit int) ([]model.
|
||||
timeDiff := currentTime - (int64(limit) * 3600)
|
||||
|
||||
db := database.GetDB()
|
||||
err = db.Model(model.Stats{}).Where("resource = ? AND tag = ? AND date_time > ?", resorce, tag, timeDiff).Scan(&result).Error
|
||||
resources := []string{resource}
|
||||
if resource == "endpoint" {
|
||||
resources = []string{"inbound", "outbound"}
|
||||
}
|
||||
err = db.Model(model.Stats{}).Where("resource in ? AND tag = ? AND date_time > ?", resources, tag, timeDiff).Scan(&result).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+37
-15
@@ -4,11 +4,13 @@ import (
|
||||
"encoding/json"
|
||||
"s-ui/database"
|
||||
"s-ui/database/model"
|
||||
"s-ui/util/common"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type TlsService struct {
|
||||
InboundService
|
||||
}
|
||||
|
||||
func (s *TlsService) GetAll() ([]model.Tls, error) {
|
||||
@@ -22,25 +24,45 @@ func (s *TlsService) GetAll() ([]model.Tls, error) {
|
||||
return tlsConfig, nil
|
||||
}
|
||||
|
||||
func (s *TlsService) Save(tx *gorm.DB, changes []model.Changes) error {
|
||||
func (s *TlsService) Save(tx *gorm.DB, action string, data json.RawMessage) ([]uint, error) {
|
||||
var err error
|
||||
for _, change := range changes {
|
||||
tlsConfig := model.Tls{}
|
||||
err = json.Unmarshal(change.Obj, &tlsConfig)
|
||||
var inboundIds []uint
|
||||
|
||||
switch action {
|
||||
case "new", "edit":
|
||||
var tls model.Tls
|
||||
err = json.Unmarshal(data, &tls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch change.Action {
|
||||
case "new":
|
||||
err = tx.Create(&tlsConfig).Error
|
||||
case "del":
|
||||
err = tx.Where("id = ?", change.Index).Delete(model.Tls{}).Error
|
||||
default:
|
||||
err = tx.Save(tlsConfig).Error
|
||||
return nil, err
|
||||
}
|
||||
err = tx.Save(&tls).Error
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
err = tx.Model(model.Inbound{}).Select("id").Where("tls_id = ?", tls.Id).Scan(&inboundIds).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return inboundIds, nil
|
||||
case "del":
|
||||
var id uint
|
||||
err = json.Unmarshal(data, &id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var inboundCount int64
|
||||
err = tx.Model(model.Inbound{}).Where("tls_id = ?", id).Count(&inboundCount).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if inboundCount > 0 {
|
||||
return nil, common.NewError("tls in use")
|
||||
}
|
||||
err = tx.Where("id = ?", id).Delete(model.Tls{}).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user