diff --git a/apis/admin/server.api b/apis/admin/server.api index 2877427..87d1f7e 100644 --- a/apis/admin/server.api +++ b/apis/admin/server.api @@ -189,14 +189,6 @@ service ppanel { @handler ToggleNodeStatus post /node/status/toggle (ToggleNodeStatusRequest) - @doc "Check if there is any server or node to migrate" - @handler HasMigrateSeverNode - get /migrate/has returns (HasMigrateSeverNodeResponse) - - @doc "Migrate server and node data to new database" - @handler MigrateServerNode - post /migrate/run returns (MigrateServerNodeResponse) - @doc "Reset server sort" @handler ResetSortWithServer post /server/sort (ResetSortRequest) diff --git a/internal/handler/admin/server/hasMigrateSeverNodeHandler.go b/internal/handler/admin/server/hasMigrateSeverNodeHandler.go deleted file mode 100644 index 6088577..0000000 --- a/internal/handler/admin/server/hasMigrateSeverNodeHandler.go +++ /dev/null @@ -1,18 +0,0 @@ -package server - -import ( - "github.com/gin-gonic/gin" - "github.com/perfect-panel/server/internal/logic/admin/server" - "github.com/perfect-panel/server/internal/svc" - "github.com/perfect-panel/server/pkg/result" -) - -// Check if there is any server or node to migrate -func HasMigrateSeverNodeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { - return func(c *gin.Context) { - - l := server.NewHasMigrateSeverNodeLogic(c.Request.Context(), svcCtx) - resp, err := l.HasMigrateSeverNode() - result.HttpResult(c, resp, err) - } -} diff --git a/internal/handler/admin/server/migrateServerNodeHandler.go b/internal/handler/admin/server/migrateServerNodeHandler.go deleted file mode 100644 index 8f8c842..0000000 --- a/internal/handler/admin/server/migrateServerNodeHandler.go +++ /dev/null @@ -1,18 +0,0 @@ -package server - -import ( - "github.com/gin-gonic/gin" - "github.com/perfect-panel/server/internal/logic/admin/server" - "github.com/perfect-panel/server/internal/svc" - "github.com/perfect-panel/server/pkg/result" -) - -// Migrate server and node data to new database -func MigrateServerNodeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { - return func(c *gin.Context) { - - l := server.NewMigrateServerNodeLogic(c.Request.Context(), svcCtx) - resp, err := l.MigrateServerNode() - result.HttpResult(c, resp, err) - } -} diff --git a/internal/handler/routes.go b/internal/handler/routes.go index e3ad493..2ac18a8 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -311,12 +311,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) { // Filter Server List adminServerGroupRouter.GET("/list", adminServer.FilterServerListHandler(serverCtx)) - // Check if there is any server or node to migrate - adminServerGroupRouter.GET("/migrate/has", adminServer.HasMigrateSeverNodeHandler(serverCtx)) - - // Migrate server and node data to new database - adminServerGroupRouter.POST("/migrate/run", adminServer.MigrateServerNodeHandler(serverCtx)) - // Create Node adminServerGroupRouter.POST("/node/create", adminServer.CreateNodeHandler(serverCtx)) diff --git a/internal/logic/admin/server/hasMigrateSeverNodeLogic.go b/internal/logic/admin/server/hasMigrateSeverNodeLogic.go deleted file mode 100644 index 128b7f6..0000000 --- a/internal/logic/admin/server/hasMigrateSeverNodeLogic.go +++ /dev/null @@ -1,52 +0,0 @@ -package server - -import ( - "context" - - "github.com/perfect-panel/server/internal/model/node" - "github.com/perfect-panel/server/internal/model/server" - "github.com/perfect-panel/server/internal/svc" - "github.com/perfect-panel/server/internal/types" - "github.com/perfect-panel/server/pkg/logger" - "github.com/perfect-panel/server/pkg/xerr" - "github.com/pkg/errors" -) - -type HasMigrateSeverNodeLogic struct { - logger.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -// NewHasMigrateSeverNodeLogic Check if there is any server or node to migrate -func NewHasMigrateSeverNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HasMigrateSeverNodeLogic { - return &HasMigrateSeverNodeLogic{ - Logger: logger.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -func (l *HasMigrateSeverNodeLogic) HasMigrateSeverNode() (resp *types.HasMigrateSeverNodeResponse, err error) { - var oldCount, newCount int64 - query := l.svcCtx.DB.WithContext(l.ctx) - - err = query.Model(&server.Server{}).Count(&oldCount).Error - if err != nil { - l.Errorw("[HasMigrateSeverNode] Query Old Server Count Error: ", logger.Field("error", err.Error())) - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "[HasMigrateSeverNode] Query Old Server Count Error") - } - err = query.Model(&node.Server{}).Count(&newCount).Error - if err != nil { - l.Errorw("[HasMigrateSeverNode] Query New Server Count Error: ", logger.Field("error", err.Error())) - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "[HasMigrateSeverNode] Query New Server Count Error") - } - var shouldMigrate bool - if oldCount != 0 && newCount == 0 { - shouldMigrate = true - } - - return &types.HasMigrateSeverNodeResponse{ - HasMigrate: shouldMigrate, - }, nil -} diff --git a/internal/logic/admin/server/migrateServerNodeLogic.go b/internal/logic/admin/server/migrateServerNodeLogic.go deleted file mode 100644 index 4f0a497..0000000 --- a/internal/logic/admin/server/migrateServerNodeLogic.go +++ /dev/null @@ -1,338 +0,0 @@ -package server - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/perfect-panel/server/internal/model/node" - "github.com/perfect-panel/server/internal/model/server" - "github.com/perfect-panel/server/internal/svc" - "github.com/perfect-panel/server/internal/types" - "github.com/perfect-panel/server/pkg/logger" -) - -type MigrateServerNodeLogic struct { - logger.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -// NewMigrateServerNodeLogic Migrate server and node data to new database -func NewMigrateServerNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MigrateServerNodeLogic { - return &MigrateServerNodeLogic{ - Logger: logger.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -func (l *MigrateServerNodeLogic) MigrateServerNode() (resp *types.MigrateServerNodeResponse, err error) { - tx := l.svcCtx.DB.WithContext(l.ctx).Begin() - var oldServers []*server.Server - var newServers []*node.Server - var newNodes []*node.Node - - err = tx.Model(&server.Server{}).Find(&oldServers).Error - if err != nil { - l.Errorw("[MigrateServerNode] Query Old Server List Error: ", logger.Field("error", err.Error())) - return &types.MigrateServerNodeResponse{ - Succee: 0, - Fail: 0, - Message: fmt.Sprintf("Query Old Server List Error: %s", err.Error()), - }, nil - } - for _, oldServer := range oldServers { - data, err := l.adapterServer(oldServer) - if err != nil { - l.Errorw("[MigrateServerNode] Adapter Server Error: ", logger.Field("error", err.Error())) - if resp == nil { - resp = &types.MigrateServerNodeResponse{} - } - resp.Fail++ - if resp.Message == "" { - resp.Message = fmt.Sprintf("Adapter Server Error: %s", err.Error()) - } else { - resp.Message = fmt.Sprintf("%s; Adapter Server Error: %s", resp.Message, err.Error()) - } - continue - } - newServers = append(newServers, data) - - newNode, err := l.adapterNode(oldServer) - if err != nil { - l.Errorw("[MigrateServerNode] Adapter Node Error: ", logger.Field("error", err.Error())) - if resp == nil { - resp = &types.MigrateServerNodeResponse{} - } - resp.Fail++ - if resp.Message == "" { - resp.Message = fmt.Sprintf("Adapter Node Error: %s", err.Error()) - } else { - resp.Message = fmt.Sprintf("%s; Adapter Node Error: %s", resp.Message, err.Error()) - } - continue - } - for _, item := range newNode { - if item.Port == 0 { - protocols, _ := data.UnmarshalProtocols() - if len(protocols) > 0 { - item.Port = protocols[0].Port - } - } - newNodes = append(newNodes, item) - } - } - - if len(newServers) > 0 { - err = tx.Model(&node.Server{}).CreateInBatches(newServers, 20).Error - if err != nil { - tx.Rollback() - l.Errorw("[MigrateServerNode] Insert New Server List Error: ", logger.Field("error", err.Error())) - return &types.MigrateServerNodeResponse{ - Succee: 0, - Fail: uint64(len(newServers)), - Message: fmt.Sprintf("Insert New Server List Error: %s", err.Error()), - }, nil - } - } - if len(newNodes) > 0 { - err = tx.Model(&node.Node{}).CreateInBatches(newNodes, 20).Error - if err != nil { - tx.Rollback() - l.Errorw("[MigrateServerNode] Insert New Node List Error: ", logger.Field("error", err.Error())) - return &types.MigrateServerNodeResponse{ - Succee: uint64(len(newServers)), - Fail: uint64(len(newNodes)), - Message: fmt.Sprintf("Insert New Node List Error: %s", err.Error()), - }, nil - } - } - tx.Commit() - - return &types.MigrateServerNodeResponse{ - Succee: uint64(len(newServers)), - Fail: 0, - Message: fmt.Sprintf("Migrate Success: %d servers and %d nodes", len(newServers), len(newNodes)), - }, nil -} - -func (l *MigrateServerNodeLogic) adapterServer(info *server.Server) (*node.Server, error) { - result := &node.Server{ - Id: info.Id, - Name: info.Name, - Country: info.Country, - City: info.City, - //Ratio: info.TrafficRatio, - Address: info.ServerAddr, - Sort: int(info.Sort), - Protocols: "", - } - var protocols []node.Protocol - - switch info.Protocol { - case ShadowSocks: - var src server.Shadowsocks - err := json.Unmarshal([]byte(info.Config), &src) - if err != nil { - return nil, err - } - protocols = append(protocols, node.Protocol{ - Type: "shadowsocks", - Cipher: src.Method, - Port: uint16(src.Port), - ServerKey: src.ServerKey, - Ratio: float64(info.TrafficRatio), - }) - case Vmess: - var src server.Vmess - err := json.Unmarshal([]byte(info.Config), &src) - if err != nil { - return nil, err - } - protocol := node.Protocol{ - Type: "vmess", - Port: uint16(src.Port), - Security: src.Security, - SNI: src.SecurityConfig.SNI, - AllowInsecure: src.SecurityConfig.AllowInsecure, - Fingerprint: src.SecurityConfig.Fingerprint, - RealityServerAddr: src.SecurityConfig.RealityServerAddr, - RealityServerPort: src.SecurityConfig.RealityServerPort, - RealityPrivateKey: src.SecurityConfig.RealityPrivateKey, - RealityPublicKey: src.SecurityConfig.RealityPublicKey, - RealityShortId: src.SecurityConfig.RealityShortId, - Transport: src.Transport, - Host: src.TransportConfig.Host, - Path: src.TransportConfig.Path, - ServiceName: src.TransportConfig.ServiceName, - Flow: src.Flow, - Ratio: float64(info.TrafficRatio), - } - protocols = append(protocols, protocol) - protocols = append(protocols, protocol) - case Vless: - var src server.Vless - err := json.Unmarshal([]byte(info.Config), &src) - if err != nil { - return nil, err - } - protocol := node.Protocol{ - Type: "vless", - Port: uint16(src.Port), - Security: src.Security, - SNI: src.SecurityConfig.SNI, - AllowInsecure: src.SecurityConfig.AllowInsecure, - Fingerprint: src.SecurityConfig.Fingerprint, - RealityServerAddr: src.SecurityConfig.RealityServerAddr, - RealityServerPort: src.SecurityConfig.RealityServerPort, - RealityPrivateKey: src.SecurityConfig.RealityPrivateKey, - RealityPublicKey: src.SecurityConfig.RealityPublicKey, - RealityShortId: src.SecurityConfig.RealityShortId, - Transport: src.Transport, - Host: src.TransportConfig.Host, - Path: src.TransportConfig.Path, - ServiceName: src.TransportConfig.ServiceName, - Flow: src.Flow, - Ratio: float64(info.TrafficRatio), - } - protocols = append(protocols, protocol) - case Trojan: - var src server.Trojan - err := json.Unmarshal([]byte(info.Config), &src) - if err != nil { - return nil, err - } - protocol := node.Protocol{ - Type: "trojan", - Port: uint16(src.Port), - Security: src.Security, - SNI: src.SecurityConfig.SNI, - AllowInsecure: src.SecurityConfig.AllowInsecure, - Fingerprint: src.SecurityConfig.Fingerprint, - RealityServerAddr: src.SecurityConfig.RealityServerAddr, - RealityServerPort: src.SecurityConfig.RealityServerPort, - RealityPrivateKey: src.SecurityConfig.RealityPrivateKey, - RealityPublicKey: src.SecurityConfig.RealityPublicKey, - RealityShortId: src.SecurityConfig.RealityShortId, - Transport: src.Transport, - Host: src.TransportConfig.Host, - Path: src.TransportConfig.Path, - ServiceName: src.TransportConfig.ServiceName, - Flow: src.Flow, - Ratio: float64(info.TrafficRatio), - } - protocols = append(protocols, protocol) - case Hysteria2: - var src server.Hysteria2 - err := json.Unmarshal([]byte(info.Config), &src) - if err != nil { - return nil, err - } - protocol := node.Protocol{ - Type: "hysteria", - Port: uint16(src.Port), - HopPorts: src.HopPorts, - HopInterval: src.HopInterval, - ObfsPassword: src.ObfsPassword, - SNI: src.SecurityConfig.SNI, - AllowInsecure: src.SecurityConfig.AllowInsecure, - Fingerprint: src.SecurityConfig.Fingerprint, - RealityServerAddr: src.SecurityConfig.RealityServerAddr, - RealityServerPort: src.SecurityConfig.RealityServerPort, - RealityPrivateKey: src.SecurityConfig.RealityPrivateKey, - RealityPublicKey: src.SecurityConfig.RealityPublicKey, - RealityShortId: src.SecurityConfig.RealityShortId, - Ratio: float64(info.TrafficRatio), - } - protocols = append(protocols, protocol) - case Tuic: - var src server.Tuic - err := json.Unmarshal([]byte(info.Config), &src) - if err != nil { - return nil, err - } - protocol := node.Protocol{ - Type: "tuic", - Port: uint16(src.Port), - DisableSNI: src.DisableSNI, - ReduceRtt: src.ReduceRtt, - UDPRelayMode: src.UDPRelayMode, - CongestionController: src.CongestionController, - SNI: src.SecurityConfig.SNI, - AllowInsecure: src.SecurityConfig.AllowInsecure, - Fingerprint: src.SecurityConfig.Fingerprint, - RealityServerAddr: src.SecurityConfig.RealityServerAddr, - RealityServerPort: src.SecurityConfig.RealityServerPort, - RealityPrivateKey: src.SecurityConfig.RealityPrivateKey, - RealityPublicKey: src.SecurityConfig.RealityPublicKey, - RealityShortId: src.SecurityConfig.RealityShortId, - Ratio: float64(info.TrafficRatio), - } - protocols = append(protocols, protocol) - case AnyTLS: - var src server.AnyTLS - err := json.Unmarshal([]byte(info.Config), &src) - if err != nil { - return nil, err - } - protocol := node.Protocol{ - Type: "anytls", - Port: uint16(src.Port), - SNI: src.SecurityConfig.SNI, - AllowInsecure: src.SecurityConfig.AllowInsecure, - Fingerprint: src.SecurityConfig.Fingerprint, - RealityServerAddr: src.SecurityConfig.RealityServerAddr, - RealityServerPort: src.SecurityConfig.RealityServerPort, - RealityPrivateKey: src.SecurityConfig.RealityPrivateKey, - RealityPublicKey: src.SecurityConfig.RealityPublicKey, - RealityShortId: src.SecurityConfig.RealityShortId, - Ratio: float64(info.TrafficRatio), - } - protocols = append(protocols, protocol) - } - if len(protocols) > 0 { - err := result.MarshalProtocols(protocols) - if err != nil { - return nil, err - } - } - - return result, nil -} - -func (l *MigrateServerNodeLogic) adapterNode(info *server.Server) ([]*node.Node, error) { - var nodes []*node.Node - enable := true - switch info.RelayMode { - case server.RelayModeNone: - nodes = append(nodes, &node.Node{ - Name: info.Name, - Tags: "", - Port: 0, - Address: info.ServerAddr, - ServerId: info.Id, - Protocol: info.Protocol, - Enabled: &enable, - }) - default: - var relays []server.NodeRelay - err := json.Unmarshal([]byte(info.RelayNode), &relays) - if err != nil { - return nil, err - } - for _, relay := range relays { - nodes = append(nodes, &node.Node{ - Name: relay.Prefix + info.Name, - Tags: "", - Port: uint16(relay.Port), - Address: relay.Host, - ServerId: info.Id, - Protocol: info.Protocol, - Enabled: &enable, - }) - } - } - - return nodes, nil -} diff --git a/internal/logic/common/getStatLogic.go b/internal/logic/common/getStatLogic.go index df14af0..f97223d 100644 --- a/internal/logic/common/getStatLogic.go +++ b/internal/logic/common/getStatLogic.go @@ -11,7 +11,7 @@ import ( "time" "github.com/perfect-panel/server/internal/config" - "github.com/perfect-panel/server/internal/model/server" + "github.com/perfect-panel/server/internal/model/node" "github.com/perfect-panel/server/internal/model/user" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" @@ -57,13 +57,13 @@ func (l *GetStatLogic) GetStat() (resp *types.GetStatResponse, err error) { u = 1 } var n int64 - err = l.svcCtx.DB.Model(&server.Server{}).Where("enable = 1").Count(&n).Error + err = l.svcCtx.DB.Model(&node.Node{}).Where("enabled = 1").Count(&n).Error if err != nil { l.Logger.Error("[GetStatLogic] get server count failed: ", logger.Field("error", err.Error())) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get server count failed: %v", err.Error()) } var nodeaddr []string - err = l.svcCtx.DB.Model(&server.Server{}).Where("enable = 1").Pluck("server_addr", &nodeaddr).Error + err = l.svcCtx.DB.Model(&node.Server{}).Pluck("address", &nodeaddr).Error if err != nil { l.Logger.Error("[GetStatLogic] get server_addr failed: ", logger.Field("error", err.Error())) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get server_addr failed: %v", err.Error()) @@ -111,9 +111,23 @@ func (l *GetStatLogic) GetStat() (resp *types.GetStatResponse, err error) { } protocolDict := make(map[string]void) var protocol []string - l.svcCtx.DB.Model(&server.Server{}).Where("enable = true").Pluck("protocol", &protocol) + err = l.svcCtx.DB.Model(&node.Node{}).Where("enabled = true").Pluck("protocol", &protocol).Error + if err != nil { + l.Logger.Error("[GetStatLogic] get protocol failed: ", logger.Field("error", err.Error())) + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get protocol failed: %v", err.Error()) + } + for _, p := range protocol { - protocolDict[p] = v + var protocols []node.Protocol + err = json.Unmarshal([]byte(p), &protocols) + if err != nil { + continue + } + for _, proto := range protocols { + if _, exists := protocolDict[proto.Type]; !exists { + protocolDict[proto.Type] = v + } + } } protocol = nil for p := range protocolDict { diff --git a/internal/model/server/default.go b/internal/model/server/default.go deleted file mode 100644 index b013f1a..0000000 --- a/internal/model/server/default.go +++ /dev/null @@ -1,141 +0,0 @@ -package server - -import ( - "context" - "errors" - "fmt" - - "github.com/perfect-panel/server/pkg/cache" - "github.com/redis/go-redis/v9" - "gorm.io/gorm" -) - -var _ Model = (*customServerModel)(nil) -var ( - cacheServerIdPrefix = "cache:server:id:" -) - -type ( - Model interface { - serverModel - customServerLogicModel - } - serverModel interface { - Insert(ctx context.Context, data *Server, tx ...*gorm.DB) error - FindOne(ctx context.Context, id int64) (*Server, error) - Update(ctx context.Context, data *Server, tx ...*gorm.DB) error - Delete(ctx context.Context, id int64, tx ...*gorm.DB) error - Transaction(ctx context.Context, fn func(db *gorm.DB) error) error - } - - customServerModel struct { - *defaultServerModel - } - defaultServerModel struct { - cache.CachedConn - table string - } -) - -func newServerModel(db *gorm.DB, c *redis.Client) *defaultServerModel { - return &defaultServerModel{ - CachedConn: cache.NewConn(db, c), - table: "`Server`", - } -} - -// NewModel returns a model for the database table. -func NewModel(conn *gorm.DB, c *redis.Client) Model { - return &customServerModel{ - defaultServerModel: newServerModel(conn, c), - } -} - -//nolint:unused -func (m *defaultServerModel) batchGetCacheKeys(Servers ...*Server) []string { - var keys []string - for _, server := range Servers { - keys = append(keys, m.getCacheKeys(server)...) - } - return keys - -} - -func (m *defaultServerModel) getCacheKeys(data *Server) []string { - if data == nil { - return []string{} - } - detailsKey := fmt.Sprintf("%s%v", CacheServerDetailPrefix, data.Id) - ServerIdKey := fmt.Sprintf("%s%v", cacheServerIdPrefix, data.Id) - //configIdKey := fmt.Sprintf("%s%v", config.ServerConfigCacheKey, data.Id) - //userIDKey := fmt.Sprintf("%s%d", config.ServerUserListCacheKey, data.Id) - - // query protocols to get config keys - - cacheKeys := []string{ - ServerIdKey, - detailsKey, - //configIdKey, - //userIDKey, - } - return cacheKeys -} - -func (m *defaultServerModel) Insert(ctx context.Context, data *Server, tx ...*gorm.DB) error { - err := m.ExecCtx(ctx, func(conn *gorm.DB) error { - if len(tx) > 0 { - conn = tx[0] - } - return conn.Create(&data).Error - }, m.getCacheKeys(data)...) - return err -} - -func (m *defaultServerModel) FindOne(ctx context.Context, id int64) (*Server, error) { - ServerIdKey := fmt.Sprintf("%s%v", cacheServerIdPrefix, id) - var resp Server - err := m.QueryCtx(ctx, &resp, ServerIdKey, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Where("`id` = ?", id).First(&resp).Error - }) - switch { - case err == nil: - return &resp, nil - default: - return nil, err - } -} - -func (m *defaultServerModel) Update(ctx context.Context, data *Server, tx ...*gorm.DB) error { - old, err := m.FindOne(ctx, data.Id) - if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { - return err - } - err = m.ExecCtx(ctx, func(conn *gorm.DB) error { - if len(tx) > 0 { - conn = tx[0] - } - return conn.Save(data).Error - }, m.getCacheKeys(old)...) - return err -} - -func (m *defaultServerModel) Delete(ctx context.Context, id int64, tx ...*gorm.DB) error { - data, err := m.FindOne(ctx, id) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil - } - return err - } - err = m.ExecCtx(ctx, func(conn *gorm.DB) error { - if len(tx) > 0 { - conn = tx[0] - } - return conn.Delete(&Server{}, id).Error - }, m.getCacheKeys(data)...) - return err -} - -func (m *defaultServerModel) Transaction(ctx context.Context, fn func(db *gorm.DB) error) error { - return m.TransactCtx(ctx, fn) -} diff --git a/internal/model/server/model.go b/internal/model/server/model.go deleted file mode 100644 index 58ae7b7..0000000 --- a/internal/model/server/model.go +++ /dev/null @@ -1,292 +0,0 @@ -package server - -import ( - "context" - "fmt" - "strings" - - "gorm.io/gorm" -) - -type customServerLogicModel interface { - FindServerListByFilter(ctx context.Context, filter *ServerFilter) (total int64, list []*Server, err error) - ClearCache(ctx context.Context, id int64) error - QueryServerCountByServerGroups(ctx context.Context, groupIds []int64) (int64, error) - QueryAllGroup(ctx context.Context) ([]*Group, error) - BatchDeleteNodeGroup(ctx context.Context, ids []int64) error - InsertGroup(ctx context.Context, data *Group) error - FindOneGroup(ctx context.Context, id int64) (*Group, error) - UpdateGroup(ctx context.Context, data *Group) error - DeleteGroup(ctx context.Context, id int64) error - FindServerDetailByGroupIdsAndIds(ctx context.Context, groupId, ids []int64) ([]*Server, error) - FindServerListByGroupIds(ctx context.Context, groupId []int64) ([]*Server, error) - FindAllServer(ctx context.Context) ([]*Server, error) - FindNodeByServerAddrAndProtocol(ctx context.Context, serverAddr string, protocol string) ([]*Server, error) - FindServerMinSortByIds(ctx context.Context, ids []int64) (int64, error) - FindServerListByIds(ctx context.Context, ids []int64) ([]*Server, error) - InsertRuleGroup(ctx context.Context, data *RuleGroup) error - FindOneRuleGroup(ctx context.Context, id int64) (*RuleGroup, error) - UpdateRuleGroup(ctx context.Context, data *RuleGroup) error - DeleteRuleGroup(ctx context.Context, id int64) error - QueryAllRuleGroup(ctx context.Context) ([]*RuleGroup, error) - FindServersByTag(ctx context.Context, tag string) ([]*Server, error) - FindServerTags(ctx context.Context) ([]string, error) - - SetDefaultRuleGroup(ctx context.Context, id int64) error -} - -var ( - CacheServerDetailPrefix = "cache:server:detail:" - cacheServerGroupAllKeys = "cache:serverGroup:all" - cacheServerRuleGroupAllKeys = "cache:serverRuleGroup:all" -) - -// ClearCache Clear Cache -func (m *customServerModel) ClearCache(ctx context.Context, id int64) error { - serverIdKey := fmt.Sprintf("%s%v", cacheServerIdPrefix, id) - //configKey := fmt.Sprintf("%s%d", config.ServerConfigCacheKey, id) - //userListKey := fmt.Sprintf("%s%v", config.ServerUserListCacheKey, id) - - return m.DelCacheCtx(ctx, serverIdKey) -} - -// QueryServerCountByServerGroups Query Server Count By Server Groups -func (m *customServerModel) QueryServerCountByServerGroups(ctx context.Context, groupIds []int64) (int64, error) { - var count int64 - err := m.QueryNoCacheCtx(ctx, &count, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Where("group_id IN ?", groupIds).Count(&count).Error - }) - return count, err -} - -// QueryAllGroup returns all groups. -func (m *customServerModel) QueryAllGroup(ctx context.Context) ([]*Group, error) { - var groups []*Group - err := m.QueryCtx(ctx, &groups, cacheServerGroupAllKeys, func(conn *gorm.DB, v interface{}) error { - return conn.Find(&groups).Error - }) - return groups, err -} - -// BatchDeleteNodeGroup deletes multiple groups. -func (m *customServerModel) BatchDeleteNodeGroup(ctx context.Context, ids []int64) error { - return m.Transaction(ctx, func(tx *gorm.DB) error { - for _, id := range ids { - if err := m.Delete(ctx, id); err != nil { - return err - } - } - return nil - }) -} - -// InsertGroup inserts a group. -func (m *customServerModel) InsertGroup(ctx context.Context, data *Group) error { - return m.ExecCtx(ctx, func(conn *gorm.DB) error { - return conn.Create(data).Error - }, cacheServerGroupAllKeys) -} - -// FindOneGroup finds a group. -func (m *customServerModel) FindOneGroup(ctx context.Context, id int64) (*Group, error) { - var group Group - err := m.QueryCtx(ctx, &group, fmt.Sprintf("cache:serverGroup:%v", id), func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Group{}).Where("id = ?", id).First(&group).Error - }) - return &group, err -} - -// UpdateGroup updates a group. -func (m *customServerModel) UpdateGroup(ctx context.Context, data *Group) error { - return m.ExecCtx(ctx, func(conn *gorm.DB) error { - return conn.Model(&Group{}).Where("id = ?", data.Id).Updates(data).Error - }, cacheServerGroupAllKeys, fmt.Sprintf("cache:serverGroup:%v", data.Id)) -} - -// DeleteGroup deletes a group. -func (m *customServerModel) DeleteGroup(ctx context.Context, id int64) error { - return m.ExecCtx(ctx, func(conn *gorm.DB) error { - return conn.Where("id = ?", id).Delete(&Group{}).Error - }, cacheServerGroupAllKeys, fmt.Sprintf("cache:serverGroup:%v", id)) -} - -// FindServerDetailByGroupIdsAndIds finds server details by group IDs and IDs. -func (m *customServerModel) FindServerDetailByGroupIdsAndIds(ctx context.Context, groupId, ids []int64) ([]*Server, error) { - if len(groupId) == 0 && len(ids) == 0 { - return []*Server{}, nil - } - var list []*Server - err := m.QueryNoCacheCtx(ctx, &list, func(conn *gorm.DB, v interface{}) error { - conn = conn. - Model(&Server{}). - Where("`enable` = ?", true) - if len(groupId) > 0 && len(ids) > 0 { - // OR is used to connect group_id and id conditions - conn = conn.Where("(`group_id` IN ? OR `id` IN ?)", groupId, ids) - } else if len(groupId) > 0 { - conn = conn.Where("`group_id` IN ?", groupId) - } else if len(ids) > 0 { - conn = conn.Where("`id` IN ?", ids) - } - - return conn.Order("sort ASC").Find(v).Error - }) - return list, err -} - -func (m *customServerModel) FindServerListByGroupIds(ctx context.Context, groupId []int64) ([]*Server, error) { - var data []*Server - err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Where("group_id IN ?", groupId).Find(v).Error - }) - return data, err -} - -func (m *customServerModel) FindAllServer(ctx context.Context) ([]*Server, error) { - var data []*Server - err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Order("sort ASC").Find(v).Error - }) - return data, err -} - -func (m *customServerModel) FindNodeByServerAddrAndProtocol(ctx context.Context, serverAddr string, protocol string) ([]*Server, error) { - var data []*Server - err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Where("server_addr = ? and protocol = ?", serverAddr, protocol).Order("sort ASC").Find(v).Error - }) - return data, err -} - -func (m *customServerModel) FindServerMinSortByIds(ctx context.Context, ids []int64) (int64, error) { - var minSort int64 - err := m.QueryNoCacheCtx(ctx, &minSort, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Where("id IN ?", ids).Select("COALESCE(MIN(sort), 0)").Scan(v).Error - }) - return minSort, err -} - -func (m *customServerModel) FindServerListByIds(ctx context.Context, ids []int64) ([]*Server, error) { - var list []*Server - err := m.QueryNoCacheCtx(ctx, &list, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Where("id IN ?", ids).Find(v).Error - }) - return list, err -} - -// InsertRuleGroup inserts a group. -func (m *customServerModel) InsertRuleGroup(ctx context.Context, data *RuleGroup) error { - return m.ExecCtx(ctx, func(conn *gorm.DB) error { - return conn.Where(&RuleGroup{}).Create(data).Error - }, cacheServerRuleGroupAllKeys, fmt.Sprintf("cache:serverRuleGroup:%v", data.Id)) -} - -// FindOneRuleGroup finds a group. -func (m *customServerModel) FindOneRuleGroup(ctx context.Context, id int64) (*RuleGroup, error) { - var group RuleGroup - err := m.QueryCtx(ctx, &group, fmt.Sprintf("cache:serverRuleGroup:%v", id), func(conn *gorm.DB, v interface{}) error { - return conn.Where(&RuleGroup{}).Model(&RuleGroup{}).Where("id = ?", id).First(&group).Error - }) - return &group, err -} - -// UpdateRuleGroup updates a group. -func (m *customServerModel) UpdateRuleGroup(ctx context.Context, data *RuleGroup) error { - return m.ExecCtx(ctx, func(conn *gorm.DB) error { - return conn.Where(&RuleGroup{}).Model(&RuleGroup{}).Where("id = ?", data.Id).Save(data).Error - }, cacheServerRuleGroupAllKeys, fmt.Sprintf("cache:serverRuleGroup:%v", data.Id)) -} - -// DeleteRuleGroup deletes a group. -func (m *customServerModel) DeleteRuleGroup(ctx context.Context, id int64) error { - return m.ExecCtx(ctx, func(conn *gorm.DB) error { - return conn.Where(&RuleGroup{}).Where("id = ?", id).Delete(&RuleGroup{}).Error - }, cacheServerRuleGroupAllKeys, fmt.Sprintf("cache:serverRuleGroup:%v", id)) -} - -// QueryAllRuleGroup returns all rule groups. -func (m *customServerModel) QueryAllRuleGroup(ctx context.Context) ([]*RuleGroup, error) { - var groups []*RuleGroup - err := m.QueryCtx(ctx, &groups, cacheServerRuleGroupAllKeys, func(conn *gorm.DB, v interface{}) error { - return conn.Where(&RuleGroup{}).Find(&groups).Error - }) - return groups, err -} - -func (m *customServerModel) FindServerListByFilter(ctx context.Context, filter *ServerFilter) (total int64, list []*Server, err error) { - var data []*Server - if filter == nil { - filter = &ServerFilter{ - Page: 1, - Size: 10, - } - } - - if filter.Page <= 0 { - filter.Page = 1 - } - if filter.Size <= 0 { - filter.Size = 10 - } - - err = m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error { - query := conn.Model(&Server{}).Order("sort ASC") - if filter.Group > 0 { - query = conn.Where("group_id = ?", filter.Group) - } - if filter.Search != "" { - query = query.Where("name LIKE ? OR server_addr LIKE ? OR tags LIKE ?", "%"+filter.Search+"%", "%"+filter.Search+"%", "%"+filter.Search+"%") - } - if len(filter.Tags) > 0 { - for i, tag := range filter.Tags { - if i == 0 { - query = query.Where("tags LIKE ?", "%"+tag+"%") - } else { - query = query.Or("tags LIKE ?", "%"+tag+"%") - } - } - } - return query.Count(&total).Limit(filter.Size).Offset((filter.Page - 1) * filter.Size).Find(v).Error - }) - if err != nil { - return 0, nil, err - } - return total, data, nil -} - -func (m *customServerModel) FindServerTags(ctx context.Context) ([]string, error) { - var data []string - err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Distinct("tags").Pluck("tags", v).Error - }) - var tags []string - for _, tag := range data { - if strings.Contains(tag, ",") { - tags = append(tags, strings.Split(tag, ",")...) - } else { - tags = append(tags, tag) - } - } - return tags, err -} - -func (m *customServerModel) FindServersByTag(ctx context.Context, tag string) ([]*Server, error) { - var data []*Server - err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error { - return conn.Model(&Server{}).Where("FIND_IN_SET(?, tags)", tag).Order("sort ASC").Find(v).Error - }) - return data, err -} - -// SetDefaultRuleGroup sets the default rule group. - -func (m *customServerModel) SetDefaultRuleGroup(ctx context.Context, id int64) error { - return m.ExecCtx(ctx, func(conn *gorm.DB) error { - // Reset all groups to not default - if err := conn.Model(&RuleGroup{}).Where("`id` != ?", id).Update("default", false).Error; err != nil { - return err - } - // Set the specified group as default - return conn.Model(&RuleGroup{}).Where("`id` = ?", id).Update("default", true).Error - }, cacheServerRuleGroupAllKeys, fmt.Sprintf("cache:serverRuleGroup:%v", id)) -} diff --git a/internal/model/server/server.go b/internal/model/server/server.go deleted file mode 100644 index 2da10da..0000000 --- a/internal/model/server/server.go +++ /dev/null @@ -1,219 +0,0 @@ -package server - -import ( - "time" - - "github.com/perfect-panel/server/pkg/logger" - - "gorm.io/gorm" -) - -const ( - RelayModeNone = "none" - RelayModeAll = "all" - RelayModeRandom = "random" - RuleGroupTypeReject = "reject" - RuleGroupTypeDefault = "default" - RuleGroupTypeDirect = "direct" -) - -type ServerFilter struct { - Id int64 - Tags []string - Group int64 - Search string - Page int - Size int -} - -// Deprecated: use internal/model/node/server.go -type Server struct { - Id int64 `gorm:"primary_key"` - Name string `gorm:"type:varchar(100);not null;default:'';comment:Node Name"` - Tags string `gorm:"type:varchar(128);not null;default:'';comment:Tags"` - Country string `gorm:"type:varchar(128);not null;default:'';comment:Country"` - City string `gorm:"type:varchar(128);not null;default:'';comment:City"` - Latitude string `gorm:"type:varchar(128);not null;default:'';comment:Latitude"` - Longitude string `gorm:"type:varchar(128);not null;default:'';comment:Longitude"` - ServerAddr string `gorm:"type:varchar(100);not null;default:'';comment:Server Address"` - RelayMode string `gorm:"type:varchar(20);not null;default:'none';comment:Relay Mode"` - RelayNode string `gorm:"type:text;comment:Relay Node"` - SpeedLimit int `gorm:"type:int;not null;default:0;comment:Speed Limit"` - TrafficRatio float32 `gorm:"type:DECIMAL(4,2);not null;default:0;comment:Traffic Ratio"` - GroupId int64 `gorm:"index:idx_group_id;type:int;default:null;comment:Group ID"` - Protocol string `gorm:"type:varchar(20);not null;default:'';comment:Protocol"` - Config string `gorm:"type:text;comment:Config"` - Enable *bool `gorm:"type:tinyint(1);not null;default:1;comment:Enabled"` - Sort int64 `gorm:"type:int;not null;default:0;comment:Sort"` - LastReportedAt time.Time `gorm:"comment:Last Reported Time"` - CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"` - UpdatedAt time.Time `gorm:"comment:Update Time"` -} - -func (*Server) TableName() string { - return "server" -} - -func (s *Server) BeforeDelete(tx *gorm.DB) error { - logger.Debugf("[Server] BeforeDelete") - if err := tx.Exec("UPDATE `server` SET sort = sort - 1 WHERE sort > ?", s.Sort).Error; err != nil { - return err - } - return nil -} - -func (s *Server) BeforeUpdate(tx *gorm.DB) error { - logger.Debugf("[Server] BeforeUpdate") - var count int64 - if err := tx.Set("gorm:query_option", "FOR UPDATE").Model(&Server{}). - Where("sort = ? AND id != ?", s.Sort, s.Id).Count(&count).Error; err != nil { - return err - } - if count > 1 { - // reorder sort - if err := reorderSort(tx); err != nil { - logger.Errorf("[Server] BeforeUpdate reorderSort error: %v", err.Error()) - return err - } - // get max sort - var maxSort int64 - if err := tx.Model(&Server{}).Select("MAX(sort)").Scan(&maxSort).Error; err != nil { - return err - } - s.Sort = maxSort + 1 - } - return nil -} - -func (s *Server) BeforeCreate(tx *gorm.DB) error { - logger.Debugf("[Server] BeforeCreate") - if s.Sort == 0 { - var maxSort int64 - if err := tx.Model(&Server{}).Select("COALESCE(MAX(sort), 0)").Scan(&maxSort).Error; err != nil { - return err - } - s.Sort = maxSort + 1 - } - return nil -} - -type Vless struct { - Port int `json:"port"` - Flow string `json:"flow"` - Transport string `json:"transport"` - TransportConfig TransportConfig `json:"transport_config"` - Security string `json:"security"` - SecurityConfig SecurityConfig `json:"security_config"` -} - -type Vmess struct { - Port int `json:"port"` - Flow string `json:"flow"` - Transport string `json:"transport"` - TransportConfig TransportConfig `json:"transport_config"` - Security string `json:"security"` - SecurityConfig SecurityConfig `json:"security_config"` -} - -type Trojan struct { - Port int `json:"port"` - Flow string `json:"flow"` - Transport string `json:"transport"` - TransportConfig TransportConfig `json:"transport_config"` - Security string `json:"security"` - SecurityConfig SecurityConfig `json:"security_config"` -} - -type Shadowsocks struct { - Method string `json:"method"` - Port int `json:"port"` - ServerKey string `json:"server_key"` -} - -type Hysteria2 struct { - Port int `json:"port"` - HopPorts string `json:"hop_ports"` - HopInterval int `json:"hop_interval"` - ObfsPassword string `json:"obfs_password"` - SecurityConfig SecurityConfig `json:"security_config"` -} - -type Tuic struct { - Port int `json:"port"` - DisableSNI bool `json:"disable_sni"` - ReduceRtt bool `json:"reduce_rtt"` - UDPRelayMode string `json:"udp_relay_mode"` - CongestionController string `json:"congestion_controller"` - SecurityConfig SecurityConfig `json:"security_config"` -} - -type AnyTLS struct { - Port int `json:"port"` - SecurityConfig SecurityConfig `json:"security_config"` -} - -type TransportConfig struct { - Path string `json:"path,omitempty"` // ws/httpupgrade - Host string `json:"host,omitempty"` - ServiceName string `json:"service_name"` // grpc -} - -type SecurityConfig struct { - SNI string `json:"sni"` - AllowInsecure bool `json:"allow_insecure"` - Fingerprint string `json:"fingerprint"` - RealityServerAddr string `json:"reality_server_addr"` - RealityServerPort int `json:"reality_server_port"` - RealityPrivateKey string `json:"reality_private_key"` - RealityPublicKey string `json:"reality_public_key"` - RealityShortId string `json:"reality_short_id"` -} - -type NodeRelay struct { - Host string `json:"host"` - Port int `json:"port"` - Prefix string `json:"prefix"` -} - -type Group struct { - Id int64 `gorm:"primary_key"` - Name string `gorm:"type:varchar(100);not null;default:'';comment:Group Name"` - Description string `gorm:"type:varchar(255);default:'';comment:Group Description"` - CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"` - UpdatedAt time.Time `gorm:"comment:Update Time"` -} - -func (Group) TableName() string { - return "server_group" -} - -type RuleGroup struct { - Id int64 `gorm:"primary_key"` - Icon string `gorm:"type:MEDIUMTEXT;comment:Rule Group Icon"` - Name string `gorm:"type:varchar(100);not null;default:'';comment:Rule Group Name"` - Type string `gorm:"type:varchar(100);not null;default:'';comment:Rule Group Type"` - Tags string `gorm:"type:text;comment:Selected Node Tags"` - Rules string `gorm:"type:MEDIUMTEXT;comment:Rules"` - Enable bool `gorm:"type:tinyint(1);not null;default:1;comment:Rule Group Enable"` - Default bool `gorm:"type:tinyint(1);not null;default:0;comment:Rule Group is Default"` - CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"` - UpdatedAt time.Time `gorm:"comment:Update Time"` -} - -func (RuleGroup) TableName() string { - return "server_rule_group" -} -func reorderSort(tx *gorm.DB) error { - var servers []Server - if err := tx.Order("sort, id").Find(&servers).Error; err != nil { - return err - } - for i, server := range servers { - if server.Sort != int64(i)+1 { - if err := tx.Exec("UPDATE `server` SET sort = ? WHERE id = ?", i+1, server.Id).Error; err != nil { - return err - } - } - } - return nil -} diff --git a/internal/types/types.go b/internal/types/types.go index 565c4ce..e6353e9 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -1557,7 +1557,7 @@ type PurchaseOrderResponse struct { type QueryAnnouncementRequest struct { Page int `form:"page"` - Size int `form:"size,default=15"` + Size int `form:"size"` Pinned *bool `form:"pinned"` Popup *bool `form:"popup"` }