feat(api): migrate server and node data handling, update related structures and logic
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/adapter"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
@@ -28,7 +29,10 @@ func NewPreviewSubscribeTemplateLogic(ctx context.Context, svcCtx *svc.ServiceCo
|
||||
}
|
||||
|
||||
func (l *PreviewSubscribeTemplateLogic) PreviewSubscribeTemplate(req *types.PreviewSubscribeTemplateRequest) (resp *types.PreviewSubscribeTemplateResponse, err error) {
|
||||
servers, err := l.svcCtx.ServerModel.FindAllServer(l.ctx)
|
||||
_, servers, err := l.svcCtx.NodeModel.FilterNodeList(l.ctx, &node.FilterNodeParams{
|
||||
Page: 1,
|
||||
Size: 1000,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorf("[PreviewSubscribeTemplateLogic] FindAllServer error: %v", err.Error())
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "FindAllServer error: %v", err.Error())
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package server
|
||||
|
||||
const (
|
||||
ShadowSocks = "shadowsocks"
|
||||
Vmess = "vmess"
|
||||
Vless = "vless"
|
||||
Trojan = "trojan"
|
||||
AnyTLS = "anytls"
|
||||
Tuic = "tuic"
|
||||
Hysteria2 = "hysteria2"
|
||||
)
|
||||
@@ -28,7 +28,7 @@ func NewFilterNodeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Fi
|
||||
}
|
||||
|
||||
func (l *FilterNodeListLogic) FilterNodeList(req *types.FilterNodeListRequest) (resp *types.FilterNodeListResponse, err error) {
|
||||
total, data, err := l.svcCtx.NodeModel.FilterNodeList(l.ctx, &node.FilterParams{
|
||||
total, data, err := l.svcCtx.NodeModel.FilterNodeList(l.ctx, &node.FilterNodeParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Search: req.Search,
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
type FilterServerListLogic struct {
|
||||
@@ -68,7 +69,9 @@ func (l *FilterServerListLogic) handlerServerStatus(id int64) types.ServerStatus
|
||||
var result types.ServerStatus
|
||||
nodeStatus, err := l.svcCtx.NodeCache.GetNodeStatus(l.ctx, id)
|
||||
if err != nil {
|
||||
l.Errorw("[handlerServerStatus] GetNodeStatus Error: ", logger.Field("error", err.Error()), logger.Field("node_id", id))
|
||||
if !errors.Is(err, redis.Nil) {
|
||||
l.Errorw("[handlerServerStatus] GetNodeStatus Error: ", logger.Field("error", err.Error()), logger.Field("node_id", id))
|
||||
}
|
||||
return result
|
||||
}
|
||||
result = types.ServerStatus{
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
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{
|
||||
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,
|
||||
})
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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: "hysteria2",
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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
|
||||
}
|
||||
@@ -48,8 +48,8 @@ func (l *CreateSubscribeLogic) CreateSubscribe(req *types.CreateSubscribeRequest
|
||||
DeviceLimit: req.DeviceLimit,
|
||||
Quota: req.Quota,
|
||||
GroupId: req.GroupId,
|
||||
ServerGroup: tool.Int64SliceToString(req.ServerGroup),
|
||||
Server: tool.Int64SliceToString(req.Server),
|
||||
Nodes: tool.Int64SliceToString(req.Nodes),
|
||||
NodeTags: tool.StringSliceToString(req.NodeTags),
|
||||
Show: req.Show,
|
||||
Sell: req.Sell,
|
||||
Sort: 0,
|
||||
|
||||
@@ -3,6 +3,7 @@ package subscribe
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
@@ -41,7 +42,7 @@ func (l *GetSubscribeDetailsLogic) GetSubscribeDetails(req *types.GetSubscribeDe
|
||||
l.Logger.Error("[GetSubscribeDetailsLogic] JSON unmarshal failed: ", logger.Field("error", err.Error()), logger.Field("discount", sub.Discount))
|
||||
}
|
||||
}
|
||||
resp.Server = tool.StringToInt64Slice(sub.Server)
|
||||
resp.ServerGroup = tool.StringToInt64Slice(sub.ServerGroup)
|
||||
resp.Nodes = tool.StringToInt64Slice(sub.Nodes)
|
||||
resp.NodeTags = strings.Split(sub.NodeTags, ",")
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package subscribe
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
@@ -47,8 +48,8 @@ func (l *GetSubscribeListLogic) GetSubscribeList(req *types.GetSubscribeListRequ
|
||||
l.Logger.Error("[GetSubscribeListLogic] JSON unmarshal failed: ", logger.Field("error", err.Error()), logger.Field("discount", item.Discount))
|
||||
}
|
||||
}
|
||||
sub.Server = tool.StringToInt64Slice(item.Server)
|
||||
sub.ServerGroup = tool.StringToInt64Slice(item.ServerGroup)
|
||||
sub.Nodes = tool.StringToInt64Slice(item.Nodes)
|
||||
sub.NodeTags = strings.Split(item.NodeTags, ",")
|
||||
resultList = append(resultList, sub)
|
||||
}
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ func (l *UpdateSubscribeLogic) UpdateSubscribe(req *types.UpdateSubscribeRequest
|
||||
DeviceLimit: req.DeviceLimit,
|
||||
Quota: req.Quota,
|
||||
GroupId: req.GroupId,
|
||||
ServerGroup: tool.Int64SliceToString(req.ServerGroup),
|
||||
Server: tool.Int64SliceToString(req.Server),
|
||||
Nodes: tool.Int64SliceToString(req.Nodes),
|
||||
NodeTags: tool.StringSliceToString(req.NodeTags),
|
||||
Show: req.Show,
|
||||
Sell: req.Sell,
|
||||
Sort: req.Sort,
|
||||
|
||||
@@ -51,7 +51,7 @@ func (l *ResetPasswordLogic) ResetPassword(req *types.ResetPasswordRequest) (res
|
||||
Success: loginStatus,
|
||||
}
|
||||
content, _ := loginLog.Marshal()
|
||||
if err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
Id: 0,
|
||||
Type: log.TypeLogin.Uint8(),
|
||||
Date: time.Now().Format("2006-01-02"),
|
||||
|
||||
@@ -59,7 +59,7 @@ func (l *TelephoneLoginLogic) TelephoneLogin(req *types.TelephoneLoginRequest, r
|
||||
Success: loginStatus,
|
||||
}
|
||||
content, _ := loginLog.Marshal()
|
||||
if err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
Id: 0,
|
||||
Type: log.TypeLogin.Uint8(),
|
||||
Date: time.Now().Format("2006-01-02"),
|
||||
|
||||
@@ -110,7 +110,7 @@ func (l *TelephoneResetPasswordLogic) TelephoneResetPassword(req *types.Telephon
|
||||
Success: token != "",
|
||||
}
|
||||
content, _ := loginLog.Marshal()
|
||||
if err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
Id: 0,
|
||||
Type: log.TypeLogin.Uint8(),
|
||||
Date: time.Now().Format("2006-01-02"),
|
||||
|
||||
@@ -165,7 +165,7 @@ func (l *TelephoneUserRegisterLogic) TelephoneUserRegister(req *types.TelephoneR
|
||||
Success: token != "",
|
||||
}
|
||||
content, _ := loginLog.Marshal()
|
||||
if err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
Id: 0,
|
||||
Type: log.TypeLogin.Uint8(),
|
||||
Date: time.Now().Format("2006-01-02"),
|
||||
@@ -188,7 +188,7 @@ func (l *TelephoneUserRegisterLogic) TelephoneUserRegister(req *types.TelephoneR
|
||||
RegisterTime: time.Now().UnixMilli(),
|
||||
}
|
||||
content, _ = registerLog.Marshal()
|
||||
if err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
Type: log.TypeRegister.Uint8(),
|
||||
ObjectID: userInfo.Id,
|
||||
Date: time.Now().Format("2006-01-02"),
|
||||
|
||||
@@ -49,7 +49,7 @@ func (l *UserLoginLogic) UserLogin(req *types.UserLoginRequest) (resp *types.Log
|
||||
Success: loginStatus,
|
||||
}
|
||||
content, _ := loginLog.Marshal()
|
||||
if err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
Type: log.TypeLogin.Uint8(),
|
||||
Date: time.Now().Format("2006-01-02"),
|
||||
ObjectID: userInfo.Id,
|
||||
|
||||
@@ -153,7 +153,7 @@ func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterRequest) (resp *
|
||||
Success: loginStatus,
|
||||
}
|
||||
content, _ := loginLog.Marshal()
|
||||
if err = l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
if err := l.svcCtx.LogModel.Insert(l.ctx, &log.SystemLog{
|
||||
Id: 0,
|
||||
Type: log.TypeLogin.Uint8(),
|
||||
Date: time.Now().Format("2006-01-02"),
|
||||
|
||||
@@ -1,3 +1,83 @@
|
||||
package server
|
||||
|
||||
const Unchanged = "Unchanged"
|
||||
const (
|
||||
Unchanged = "Unchanged"
|
||||
ShadowSocks = "shadowsocks"
|
||||
Vmess = "vmess"
|
||||
Vless = "vless"
|
||||
Trojan = "trojan"
|
||||
AnyTLS = "anytls"
|
||||
Tuic = "tuic"
|
||||
Hysteria2 = "hysteria2"
|
||||
)
|
||||
|
||||
type SecurityConfig struct {
|
||||
SNI string `json:"sni"`
|
||||
AllowInsecure *bool `json:"allow_insecure"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
RealityServerAddress 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"`
|
||||
RealityMldsa65seed string `json:"reality_mldsa65seed"`
|
||||
}
|
||||
|
||||
type TransportConfig struct {
|
||||
Path string `json:"path"`
|
||||
Host string `json:"host"`
|
||||
ServiceName string `json:"service_name"`
|
||||
DisableSNI bool `json:"disable_sni"`
|
||||
ReduceRtt bool `json:"reduce_rtt"`
|
||||
UDPRelayMode string `json:"udp_relay_mode"`
|
||||
CongestionController string `json:"congestion_controller"`
|
||||
}
|
||||
|
||||
type VlessNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
Flow string `json:"flow"`
|
||||
Network string `json:"transport"`
|
||||
TransportConfig *TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type VmessNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
Network string `json:"transport"`
|
||||
TransportConfig *TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type ShadowsocksNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
Cipher string `json:"method"`
|
||||
ServerKey string `json:"server_key"`
|
||||
}
|
||||
|
||||
type TrojanNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
Network string `json:"transport"`
|
||||
TransportConfig *TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type AnyTLSNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type TuicNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type Hysteria2Node struct {
|
||||
Port uint16 `json:"port"`
|
||||
HopPorts string `json:"hop_ports"`
|
||||
HopInterval int `json:"hop_interval"`
|
||||
ObfsPassword string `json:"obfs_password"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
@@ -51,21 +51,21 @@ func (l *GetServerConfigLogic) GetServerConfig(req *types.GetServerConfigRequest
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
nodeInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
data, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil {
|
||||
l.Errorw("[GetServerConfig] FindOne error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
cfg := make(map[string]interface{})
|
||||
err = json.Unmarshal([]byte(nodeInfo.Config), &cfg)
|
||||
|
||||
protocols, err := data.UnmarshalProtocols()
|
||||
if err != nil {
|
||||
l.Errorw("[GetServerConfig] json unmarshal error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if nodeInfo.Protocol == "shadowsocks" {
|
||||
if value, ok := cfg["server_key"]; ok && value != "" {
|
||||
cfg["server_key"] = base64.StdEncoding.EncodeToString([]byte(value.(string)))
|
||||
var cfg map[string]interface{}
|
||||
for _, protocol := range protocols {
|
||||
if protocol.Type == req.Protocol {
|
||||
cfg = l.compatible(protocol)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,18 +74,162 @@ func (l *GetServerConfigLogic) GetServerConfig(req *types.GetServerConfigRequest
|
||||
PullInterval: l.svcCtx.Config.Node.NodePullInterval,
|
||||
PushInterval: l.svcCtx.Config.Node.NodePushInterval,
|
||||
},
|
||||
Protocol: nodeInfo.Protocol,
|
||||
Protocol: req.Protocol,
|
||||
Config: cfg,
|
||||
}
|
||||
data, err := json.Marshal(resp)
|
||||
c, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
l.Errorw("[GetServerConfig] json marshal error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
etag := tool.GenerateETag(data)
|
||||
etag := tool.GenerateETag(c)
|
||||
l.ctx.Header("ETag", etag)
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, cacheKey, data, -1).Err(); err != nil {
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, cacheKey, c, -1).Err(); err != nil {
|
||||
l.Errorw("[GetServerConfig] redis set error", logger.Field("error", err.Error()))
|
||||
}
|
||||
// Check If-None-Match header
|
||||
match := l.ctx.GetHeader("If-None-Match")
|
||||
if match == etag {
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (l *GetServerConfigLogic) compatible(config node.Protocol) map[string]interface{} {
|
||||
var result interface{}
|
||||
switch config.Type {
|
||||
case ShadowSocks:
|
||||
result = ShadowsocksNode{
|
||||
Port: config.Port,
|
||||
Cipher: config.Cipher,
|
||||
ServerKey: config.ServerKey,
|
||||
}
|
||||
case Vless:
|
||||
result = VlessNode{
|
||||
Port: config.Port,
|
||||
Flow: config.Flow,
|
||||
Network: config.Transport,
|
||||
TransportConfig: &TransportConfig{
|
||||
Path: config.Path,
|
||||
Host: config.Host,
|
||||
ServiceName: config.ServiceName,
|
||||
DisableSNI: config.DisableSNI,
|
||||
ReduceRtt: config.ReduceRtt,
|
||||
UDPRelayMode: config.UDPRelayMode,
|
||||
CongestionController: config.CongestionController,
|
||||
},
|
||||
Security: config.Security,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case Vmess:
|
||||
result = VmessNode{
|
||||
Port: config.Port,
|
||||
Network: config.Transport,
|
||||
TransportConfig: &TransportConfig{
|
||||
Path: config.Path,
|
||||
Host: config.Host,
|
||||
ServiceName: config.ServiceName,
|
||||
DisableSNI: config.DisableSNI,
|
||||
ReduceRtt: config.ReduceRtt,
|
||||
UDPRelayMode: config.UDPRelayMode,
|
||||
CongestionController: config.CongestionController,
|
||||
},
|
||||
Security: config.Security,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case Trojan:
|
||||
result = TrojanNode{
|
||||
Port: config.Port,
|
||||
Network: config.Transport,
|
||||
TransportConfig: &TransportConfig{
|
||||
Path: config.Path,
|
||||
Host: config.Host,
|
||||
ServiceName: config.ServiceName,
|
||||
DisableSNI: config.DisableSNI,
|
||||
ReduceRtt: config.ReduceRtt,
|
||||
UDPRelayMode: config.UDPRelayMode,
|
||||
CongestionController: config.CongestionController,
|
||||
},
|
||||
Security: config.Security,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case AnyTLS:
|
||||
result = AnyTLSNode{
|
||||
Port: config.Port,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case Tuic:
|
||||
result = TuicNode{
|
||||
Port: config.Port,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case Hysteria2:
|
||||
result = Hysteria2Node{
|
||||
Port: config.Port,
|
||||
HopPorts: config.HopPorts,
|
||||
HopInterval: config.HopInterval,
|
||||
ObfsPassword: config.ObfsPassword,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
var resp map[string]interface{}
|
||||
s, _ := json.Marshal(result)
|
||||
_ = json.Unmarshal(s, &resp)
|
||||
return resp
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ package server
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
@@ -33,28 +35,46 @@ func NewGetServerUserListLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *Ge
|
||||
func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListRequest) (resp *types.GetServerUserListResponse, err error) {
|
||||
cacheKey := fmt.Sprintf("%s%d", config.ServerUserListCacheKey, req.ServerId)
|
||||
cache, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
if cache != "" {
|
||||
etag := tool.GenerateETag([]byte(cache))
|
||||
resp := &types.GetServerUserListResponse{}
|
||||
// Check If-None-Match header
|
||||
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
l.ctx.Header("ETag", etag)
|
||||
err = json.Unmarshal([]byte(cache), resp)
|
||||
if err != nil {
|
||||
l.Errorw("[ServerUserListCacheKey] json unmarshal error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
if cache != "" {
|
||||
etag := tool.GenerateETag([]byte(cache))
|
||||
resp = &types.GetServerUserListResponse{}
|
||||
// Check If-None-Match header
|
||||
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
l.ctx.Header("ETag", etag)
|
||||
err = json.Unmarshal([]byte(cache), resp)
|
||||
if err != nil {
|
||||
l.Errorw("[ServerUserListCacheKey] json unmarshal error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
server, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
server, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subs, err := l.svcCtx.SubscribeModel.QuerySubscribeIdsByServerIdAndServerGroupId(l.ctx, server.Id, server.GroupId)
|
||||
|
||||
_, nodes, err := l.svcCtx.NodeModel.FilterNodeList(l.ctx, &node.FilterNodeParams{
|
||||
Page: 1,
|
||||
Size: 1000,
|
||||
ServerId: []int64{server.Id},
|
||||
Protocol: req.Protocol,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("FilterNodeList error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
var nodeTag []string
|
||||
var nodeIds []int64
|
||||
for _, n := range nodes {
|
||||
nodeIds = append(nodeIds, n.Id)
|
||||
if n.Tags != "" {
|
||||
nodeTag = append(nodeTag, strings.Split(n.Tags, ",")...)
|
||||
}
|
||||
}
|
||||
|
||||
subs, err := l.svcCtx.SubscribeModel.QuerySubscribeIdsByNodeIdAndNodeTag(l.ctx, nodeIds, nodeTag)
|
||||
if err != nil {
|
||||
l.Errorw("QuerySubscribeIdsByServerIdAndServerGroupId error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
@@ -76,16 +96,10 @@ func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListR
|
||||
return nil, err
|
||||
}
|
||||
for _, datum := range data {
|
||||
speedLimit := server.SpeedLimit
|
||||
if (int(sub.SpeedLimit) < server.SpeedLimit && sub.SpeedLimit != 0) ||
|
||||
(int(sub.SpeedLimit) > server.SpeedLimit && sub.SpeedLimit == 0) {
|
||||
speedLimit = int(sub.SpeedLimit)
|
||||
}
|
||||
|
||||
users = append(users, types.ServerUser{
|
||||
Id: datum.Id,
|
||||
UUID: datum.UUID,
|
||||
SpeedLimit: int64(speedLimit),
|
||||
SpeedLimit: sub.SpeedLimit,
|
||||
DeviceLimit: sub.DeviceLimit,
|
||||
})
|
||||
}
|
||||
@@ -106,5 +120,9 @@ func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListR
|
||||
if err != nil {
|
||||
l.Errorw("[ServerUserListCacheKey] redis set error", logger.Field("error", err.Error()))
|
||||
}
|
||||
// Check If-None-Match header
|
||||
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func (l *PushOnlineUsersLogic) PushOnlineUsers(req *types.OnlineUsersRequest) er
|
||||
}
|
||||
|
||||
// Find server info
|
||||
_, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
_, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil {
|
||||
l.Errorw("[PushOnlineUsers] FindOne error", logger.Field("error", err))
|
||||
return fmt.Errorf("server not found: %w", err)
|
||||
|
||||
@@ -27,7 +27,7 @@ func NewServerPushStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
|
||||
|
||||
func (l *ServerPushStatusLogic) ServerPushStatus(req *types.ServerPushStatusRequest) error {
|
||||
// Find server info
|
||||
serverInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
serverInfo, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil || serverInfo.Id <= 0 {
|
||||
l.Errorw("[PushOnlineUsers] FindOne error", logger.Field("error", err))
|
||||
return errors.New("server not found")
|
||||
|
||||
@@ -32,7 +32,7 @@ func NewServerPushUserTrafficLogic(ctx context.Context, svcCtx *svc.ServiceConte
|
||||
|
||||
func (l *ServerPushUserTrafficLogic) ServerPushUserTraffic(req *types.ServerPushUserTrafficRequest) error {
|
||||
// Find server info
|
||||
serverInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
serverInfo, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil {
|
||||
l.Errorw("[PushOnlineUsers] FindOne error", logger.Field("error", err))
|
||||
return errors.New("server not found")
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/perfect-panel/server/adapter"
|
||||
"github.com/perfect-panel/server/internal/model/client"
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"github.com/perfect-panel/server/internal/model/server"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
|
||||
@@ -196,7 +196,7 @@ func (l *SubscribeLogic) logSubscribeActivity(subscribeStatus bool, userSub *use
|
||||
}
|
||||
}
|
||||
|
||||
func (l *SubscribeLogic) getServers(userSub *user.Subscribe) ([]*server.Server, error) {
|
||||
func (l *SubscribeLogic) getServers(userSub *user.Subscribe) ([]*node.Node, error) {
|
||||
if l.isSubscriptionExpired(userSub) {
|
||||
return l.createExpiredServers(), nil
|
||||
}
|
||||
@@ -207,49 +207,61 @@ func (l *SubscribeLogic) getServers(userSub *user.Subscribe) ([]*server.Server,
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find subscribe details error: %v", err.Error())
|
||||
}
|
||||
|
||||
serverIds := tool.StringToInt64Slice(subDetails.Server)
|
||||
groupIds := tool.StringToInt64Slice(subDetails.ServerGroup)
|
||||
nodeIds := tool.StringToInt64Slice(subDetails.Nodes)
|
||||
tags := strings.Split(subDetails.NodeTags, ",")
|
||||
|
||||
l.Debugf("[Generate Subscribe]serverIds: %v, groupIds: %v", serverIds, groupIds)
|
||||
l.Debugf("[Generate Subscribe]nodes: %v, NodeTags: %v", nodeIds, tags)
|
||||
|
||||
servers, err := l.svc.ServerModel.FindServerDetailByGroupIdsAndIds(l.ctx.Request.Context(), groupIds, serverIds)
|
||||
_, nodes, err := l.svc.NodeModel.FilterNodeList(l.ctx.Request.Context(), &node.FilterNodeParams{
|
||||
Page: 1,
|
||||
Size: 1000,
|
||||
ServerId: nodeIds,
|
||||
Tag: tags,
|
||||
Preload: true,
|
||||
})
|
||||
|
||||
l.Debugf("[Query Subscribe]found servers: %v", len(servers))
|
||||
l.Debugf("[Query Subscribe]found servers: %v", len(nodes))
|
||||
|
||||
if err != nil {
|
||||
l.Errorw("[Generate Subscribe]find server details error: %v", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find server details error: %v", err.Error())
|
||||
}
|
||||
logger.Debugf("[Generate Subscribe]found servers: %v", len(servers))
|
||||
return servers, nil
|
||||
logger.Debugf("[Generate Subscribe]found servers: %v", len(nodes))
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func (l *SubscribeLogic) isSubscriptionExpired(userSub *user.Subscribe) bool {
|
||||
return userSub.ExpireTime.Unix() < time.Now().Unix() && userSub.ExpireTime.Unix() != 0
|
||||
}
|
||||
|
||||
func (l *SubscribeLogic) createExpiredServers() []*server.Server {
|
||||
func (l *SubscribeLogic) createExpiredServers() []*node.Node {
|
||||
enable := true
|
||||
host := l.getFirstHostLine()
|
||||
|
||||
return []*server.Server{
|
||||
return []*node.Node{
|
||||
{
|
||||
Name: "Subscribe Expired",
|
||||
ServerAddr: "127.0.0.1",
|
||||
RelayMode: "none",
|
||||
Protocol: "shadowsocks",
|
||||
Config: "{\"method\":\"aes-256-gcm\",\"port\":1}",
|
||||
Enable: &enable,
|
||||
Sort: 0,
|
||||
Name: "Subscribe Expired",
|
||||
Tags: "",
|
||||
Port: 18080,
|
||||
Address: "127.0.0.1",
|
||||
Server: &node.Server{
|
||||
Name: "Subscribe Expired",
|
||||
Protocols: "[{\"type:\"\"shadowsocks\",\"cipher\":\"aes-256-gcm\",\"port\":1}]",
|
||||
},
|
||||
Protocol: "shadowsocks",
|
||||
Enabled: &enable,
|
||||
},
|
||||
{
|
||||
Name: host,
|
||||
ServerAddr: "127.0.0.1",
|
||||
RelayMode: "none",
|
||||
Protocol: "shadowsocks",
|
||||
Config: "{\"method\":\"aes-256-gcm\",\"port\":1}",
|
||||
Enable: &enable,
|
||||
Sort: 0,
|
||||
Name: host,
|
||||
Tags: "",
|
||||
Port: 18080,
|
||||
Address: "127.0.0.1",
|
||||
Server: &node.Server{
|
||||
Name: "Subscribe Expired",
|
||||
Protocols: "[{\"type:\"\"shadowsocks\",\"cipher\":\"aes-256-gcm\",\"port\":1}]",
|
||||
},
|
||||
Protocol: "shadowsocks",
|
||||
Enabled: &enable,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user