feat(server): implement server management handlers and database schema
This commit is contained in:
@@ -6,12 +6,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type QueryServerTotalDataLogic struct {
|
||||
@@ -42,121 +39,6 @@ func (l *QueryServerTotalDataLogic) QueryServerTotalData() (resp *types.ServerTo
|
||||
UserTrafficRankingYesterday: make([]types.UserTrafficData, 0),
|
||||
}
|
||||
|
||||
// Query node server status
|
||||
servers, err := l.svcCtx.ServerModel.FindAllServer(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] FindAllServer error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(err, "FindAllServer error: %v", err)
|
||||
}
|
||||
onlineServers, err := l.svcCtx.NodeCache.GetOnlineNodeStatusCount(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] GetOnlineNodeStatusCount error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(err, "GetOnlineNodeStatusCount error: %v", err)
|
||||
}
|
||||
resp.OnlineServers = onlineServers
|
||||
resp.OfflineServers = int64(len(servers) - int(onlineServers))
|
||||
|
||||
// 获取所有节点在线用户
|
||||
allNodeOnlineUser, err := l.svcCtx.NodeCache.GetAllNodeOnlineUser(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] Get all node online user failed", logger.Field("error", err.Error()))
|
||||
}
|
||||
resp.OnlineUserIPs = int64(len(allNodeOnlineUser))
|
||||
|
||||
// 获取所有节点今日上传下载流量
|
||||
allNodeUploadTraffic, err := l.svcCtx.NodeCache.GetAllNodeUploadTraffic(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] Get all node upload traffic failed", logger.Field("error", err.Error()))
|
||||
}
|
||||
resp.TodayUpload = allNodeUploadTraffic
|
||||
allNodeDownloadTraffic, err := l.svcCtx.NodeCache.GetAllNodeDownloadTraffic(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] Get all node download traffic failed", logger.Field("error", err.Error()))
|
||||
}
|
||||
resp.TodayDownload = allNodeDownloadTraffic
|
||||
// 获取节点流量排行榜 前10
|
||||
nodeTrafficRankingToday, err := l.svcCtx.NodeCache.GetNodeTodayTotalTrafficRank(l.ctx, 10)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] Get node today total traffic rank failed", logger.Field("error", err.Error()))
|
||||
}
|
||||
if len(nodeTrafficRankingToday) > 0 {
|
||||
var serverTrafficData []types.ServerTrafficData
|
||||
for _, rank := range nodeTrafficRankingToday {
|
||||
serverInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, rank.ID)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] FindOne error", logger.Field("error", err))
|
||||
continue
|
||||
}
|
||||
serverTrafficData = append(serverTrafficData, types.ServerTrafficData{
|
||||
ServerId: rank.ID,
|
||||
Name: serverInfo.Name,
|
||||
Upload: rank.Upload,
|
||||
Download: rank.Download,
|
||||
})
|
||||
}
|
||||
resp.ServerTrafficRankingToday = serverTrafficData
|
||||
}
|
||||
// 获取用户流量排行榜 前10
|
||||
userTrafficRankingToday, err := l.svcCtx.NodeCache.GetUserTodayTotalTrafficRank(l.ctx, 10)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] Get user today total traffic rank failed", logger.Field("error", err.Error()))
|
||||
}
|
||||
|
||||
if len(userTrafficRankingToday) > 0 {
|
||||
var userTrafficData []types.UserTrafficData
|
||||
for _, rank := range userTrafficRankingToday {
|
||||
userTrafficData = append(userTrafficData, types.UserTrafficData{
|
||||
SID: rank.SID,
|
||||
Upload: rank.Upload,
|
||||
Download: rank.Download,
|
||||
})
|
||||
}
|
||||
resp.UserTrafficRankingToday = userTrafficData
|
||||
}
|
||||
// 获取昨日节点流量排行榜 前10
|
||||
nodeTrafficRankingYesterday, err := l.svcCtx.NodeCache.GetYesterdayNodeTotalTrafficRank(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] Get yesterday node total traffic rank failed", logger.Field("error", err.Error()))
|
||||
}
|
||||
if len(nodeTrafficRankingYesterday) > 0 {
|
||||
var serverTrafficData []types.ServerTrafficData
|
||||
for _, rank := range nodeTrafficRankingYesterday {
|
||||
serverTrafficData = append(serverTrafficData, types.ServerTrafficData{
|
||||
ServerId: rank.ID,
|
||||
Name: rank.Name,
|
||||
Upload: rank.Upload,
|
||||
Download: rank.Download,
|
||||
})
|
||||
}
|
||||
resp.ServerTrafficRankingYesterday = serverTrafficData
|
||||
}
|
||||
// 获取昨日用户流量排行榜 前10
|
||||
userTrafficRankingYesterday, err := l.svcCtx.NodeCache.GetYesterdayUserTotalTrafficRank(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] Get yesterday user total traffic rank failed", logger.Field("error", err.Error()))
|
||||
}
|
||||
if len(userTrafficRankingYesterday) > 0 {
|
||||
var userTrafficData []types.UserTrafficData
|
||||
for _, rank := range userTrafficRankingYesterday {
|
||||
userTrafficData = append(userTrafficData, types.UserTrafficData{
|
||||
SID: rank.SID,
|
||||
Upload: rank.Upload,
|
||||
Download: rank.Download,
|
||||
})
|
||||
}
|
||||
resp.UserTrafficRankingYesterday = userTrafficData
|
||||
}
|
||||
|
||||
// Query node traffic by monthly
|
||||
nodeTraffic, err := l.svcCtx.TrafficLogModel.QueryTrafficByMonthly(l.ctx, time.Now())
|
||||
|
||||
if err != nil {
|
||||
l.Errorw("[QueryServerTotalDataLogic] QueryTrafficByMonthly error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "QueryTrafficByMonthly error: %v", err.Error())
|
||||
}
|
||||
resp.MonthlyUpload = nodeTraffic.Upload
|
||||
resp.MonthlyDownload = nodeTraffic.Download
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterBalanceLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterBalanceLogLogic Filter balance log
|
||||
func NewFilterBalanceLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterBalanceLogLogic {
|
||||
return &FilterBalanceLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterBalanceLogLogic) FilterBalanceLog(req *types.FilterBalanceLogRequest) (resp *types.FilterBalanceLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeBalance.Uint8(),
|
||||
Data: req.Date,
|
||||
ObjectID: req.UserId,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorw("[FilterBalanceLog] Query User Balance Log Error:", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "Query User Balance Log Error")
|
||||
}
|
||||
|
||||
list := make([]types.BalanceLog, 0)
|
||||
for _, datum := range data {
|
||||
var content log.Balance
|
||||
if err = content.Unmarshal([]byte(datum.Content)); err != nil {
|
||||
l.Errorf("[QueryUserBalanceLog] unmarshal balance log content failed: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.BalanceLog{
|
||||
UserId: datum.ObjectID,
|
||||
Amount: content.Amount,
|
||||
Type: content.Type,
|
||||
OrderId: content.OrderId,
|
||||
Balance: content.Balance,
|
||||
Timestamp: content.Timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
return &types.FilterBalanceLogResponse{
|
||||
Total: total,
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterCommissionLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterCommissionLogLogic Filter commission log
|
||||
func NewFilterCommissionLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterCommissionLogLogic {
|
||||
return &FilterCommissionLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterCommissionLogLogic) FilterCommissionLog(req *types.FilterCommissionLogRequest) (resp *types.FilterCommissionLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Data: req.Date,
|
||||
Type: log.TypeCommission.Uint8(),
|
||||
ObjectID: req.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("Query User Commission Log failed", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "Query User Commission Log failed")
|
||||
}
|
||||
var list []types.CommissionLog
|
||||
|
||||
for _, datum := range data {
|
||||
var content log.Commission
|
||||
if err = content.Unmarshal([]byte(datum.Content)); err != nil {
|
||||
l.Errorf("unmarshal commission log content failed: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.CommissionLog{
|
||||
UserId: datum.ObjectID,
|
||||
Type: content.Type,
|
||||
Amount: content.Amount,
|
||||
OrderNo: content.OrderNo,
|
||||
CreatedAt: content.CreatedAt,
|
||||
})
|
||||
}
|
||||
return &types.FilterCommissionLogResponse{
|
||||
Total: total,
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterEmailLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterEmailLogLogic Filter email log
|
||||
func NewFilterEmailLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterEmailLogLogic {
|
||||
return &FilterEmailLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterEmailLogLogic) FilterEmailLog(req *types.FilterLogParams) (resp *types.FilterEmailLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeEmailMessage.Uint8(),
|
||||
Data: req.Date,
|
||||
Search: req.Search,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorf("[FilterEmailLog] failed to filter system log: %v", err.Error())
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "failed to filter system log: %v", err.Error())
|
||||
}
|
||||
|
||||
var list []types.MessageLog
|
||||
|
||||
for _, datum := range data {
|
||||
var content log.Message
|
||||
err = content.Unmarshal([]byte(datum.Content))
|
||||
if err != nil {
|
||||
l.Errorf("[FilterEmailLog] failed to unmarshal content: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.MessageLog{
|
||||
Id: datum.Id,
|
||||
Type: datum.Type,
|
||||
Platform: content.Platform,
|
||||
To: content.To,
|
||||
Subject: content.Subject,
|
||||
Content: content.Content,
|
||||
Status: content.Status,
|
||||
CreatedAt: datum.CreatedAt.UnixMilli(),
|
||||
})
|
||||
}
|
||||
|
||||
return &types.FilterEmailLogResponse{
|
||||
Total: total,
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterGiftLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Filter gift log
|
||||
func NewFilterGiftLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterGiftLogLogic {
|
||||
return &FilterGiftLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterGiftLogLogic) FilterGiftLog(req *types.FilterGiftLogRequest) (resp *types.FilterGiftLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeGift.Uint8(),
|
||||
ObjectID: req.UserId,
|
||||
Data: req.Date,
|
||||
Search: req.Search,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorf("[FilterGiftLog] failed to filter system log: %v", err.Error())
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "failed to filter system log: %v", err.Error())
|
||||
}
|
||||
|
||||
var list []types.GiftLog
|
||||
for _, datum := range data {
|
||||
var content log.Gift
|
||||
err = content.Unmarshal([]byte(datum.Content))
|
||||
if err != nil {
|
||||
l.Errorf("[FilterGiftLog] failed to unmarshal content: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.GiftLog{
|
||||
Type: content.Type,
|
||||
UserId: datum.ObjectID,
|
||||
OrderNo: content.OrderNo,
|
||||
SubscribeId: content.SubscribeId,
|
||||
Amount: content.Amount,
|
||||
Balance: content.Balance,
|
||||
Remark: content.Remark,
|
||||
CreatedAt: content.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
return &types.FilterGiftLogResponse{
|
||||
Total: total,
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterLoginLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterLoginLogLogic Filter login log
|
||||
func NewFilterLoginLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterLoginLogLogic {
|
||||
return &FilterLoginLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterLoginLogLogic) FilterLoginLog(req *types.FilterLoginLogRequest) (resp *types.FilterLoginLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeLogin.Uint8(),
|
||||
ObjectID: req.UserId,
|
||||
Data: req.Date,
|
||||
Search: req.Search,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorf("[FilterLoginLog] failed to filter system log: %v", err.Error())
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "failed to filter system log: %v", err.Error())
|
||||
}
|
||||
var list []types.LoginLog
|
||||
for _, datum := range data {
|
||||
var item log.Login
|
||||
err = item.Unmarshal([]byte(datum.Content))
|
||||
if err != nil {
|
||||
l.Errorf("[FilterLoginLog] failed to unmarshal content: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.LoginLog{
|
||||
UserId: datum.ObjectID,
|
||||
Method: item.Method,
|
||||
LoginIP: item.LoginIP,
|
||||
UserAgent: item.UserAgent,
|
||||
Success: item.Success,
|
||||
LoginTime: item.LoginTime,
|
||||
})
|
||||
}
|
||||
|
||||
return &types.FilterLoginLogResponse{
|
||||
Total: total,
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterMobileLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Filter mobile log
|
||||
func NewFilterMobileLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterMobileLogLogic {
|
||||
return &FilterMobileLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterMobileLogLogic) FilterMobileLog(req *types.FilterLogParams) (resp *types.FilterMobileLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeMobileMessage.Uint8(),
|
||||
Data: req.Date,
|
||||
Search: req.Search,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorf("[FilterMobileLog] failed to filter system log: %v", err.Error())
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "failed to filter system log: %v", err.Error())
|
||||
}
|
||||
|
||||
var list []types.MessageLog
|
||||
|
||||
for _, datum := range data {
|
||||
var content log.Message
|
||||
err = content.Unmarshal([]byte(datum.Content))
|
||||
if err != nil {
|
||||
l.Errorf("[FilterMobileLog] failed to unmarshal content: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.MessageLog{
|
||||
Id: datum.Id,
|
||||
Type: datum.Type,
|
||||
Platform: content.Platform,
|
||||
To: content.To,
|
||||
Subject: content.Subject,
|
||||
Content: content.Content,
|
||||
Status: content.Status,
|
||||
CreatedAt: datum.CreatedAt.UnixMilli(),
|
||||
})
|
||||
}
|
||||
|
||||
return &types.FilterMobileLogResponse{
|
||||
Total: total,
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterRegisterLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Filter register log
|
||||
func NewFilterRegisterLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterRegisterLogLogic {
|
||||
return &FilterRegisterLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterRegisterLogLogic) FilterRegisterLog(req *types.FilterRegisterLogRequest) (resp *types.FilterRegisterLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeRegister.Uint8(),
|
||||
ObjectID: req.UserId,
|
||||
Data: req.Date,
|
||||
Search: req.Search,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorf("[FilterRegisterLog] failed to filter system log: %v", err.Error())
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "failed to filter system log: %v", err.Error())
|
||||
}
|
||||
|
||||
var list []types.RegisterLog
|
||||
for _, datum := range data {
|
||||
var item log.Register
|
||||
err = item.Unmarshal([]byte(datum.Content))
|
||||
if err != nil {
|
||||
l.Errorf("[FilterLoginLog] failed to unmarshal content: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.RegisterLog{
|
||||
UserId: datum.ObjectID,
|
||||
AuthMethod: item.AuthMethod,
|
||||
Identifier: item.Identifier,
|
||||
RegisterIP: item.RegisterIP,
|
||||
UserAgent: item.UserAgent,
|
||||
RegisterTime: item.RegisterTime,
|
||||
})
|
||||
}
|
||||
|
||||
return &types.FilterRegisterLogResponse{
|
||||
List: list,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterResetSubscribeLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterResetSubscribeLogLogic Filter reset subscribe log
|
||||
func NewFilterResetSubscribeLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterResetSubscribeLogLogic {
|
||||
return &FilterResetSubscribeLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterResetSubscribeLogLogic) FilterResetSubscribeLog(req *types.FilterResetSubscribeLogRequest) (resp *types.FilterResetSubscribeLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeRegister.Uint8(),
|
||||
ObjectID: req.UserSubscribeId,
|
||||
Data: req.Date,
|
||||
Search: req.Search,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorf("[FilterResetSubscribeLog] failed to filter system log: %v", err.Error())
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "failed to filter system log: %v", err.Error())
|
||||
}
|
||||
|
||||
var list []types.ResetSubscribeLog
|
||||
|
||||
for _, item := range data {
|
||||
var content log.ResetSubscribe
|
||||
err = content.Unmarshal([]byte(item.Content))
|
||||
if err != nil {
|
||||
l.Errorf("[FilterResetSubscribeLog] failed to unmarshal content: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.ResetSubscribeLog{
|
||||
Type: content.Type,
|
||||
UserId: content.UserId,
|
||||
UserSubscribeId: item.ObjectID,
|
||||
OrderNo: content.OrderNo,
|
||||
ResetAt: content.ResetAt,
|
||||
})
|
||||
}
|
||||
|
||||
return &types.FilterResetSubscribeLogResponse{
|
||||
List: list,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type FilterServerTrafficLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterServerTrafficLogLogic Filter server traffic log
|
||||
func NewFilterServerTrafficLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterServerTrafficLogLogic {
|
||||
return &FilterServerTrafficLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterServerTrafficLogLogic) FilterServerTrafficLog(req *types.FilterServerTrafficLogRequest) (resp *types.FilterServerTrafficLogResponse, err error) {
|
||||
today := time.Now().Format("2006-01-02")
|
||||
if req.Date == "" || req.Date == today {
|
||||
return l.handlerToday(req)
|
||||
} else {
|
||||
return l.handlerSpecify(req)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterServerTrafficLogLogic) handlerToday(req *types.FilterServerTrafficLogRequest) (resp *types.FilterServerTrafficLogResponse, err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (l *FilterServerTrafficLogLogic) handlerSpecify(req *types.FilterServerTrafficLogRequest) (resp *types.FilterServerTrafficLogResponse, err error) {
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"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 FilterSubscribeLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Filter subscribe log
|
||||
func NewFilterSubscribeLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterSubscribeLogLogic {
|
||||
return &FilterSubscribeLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterSubscribeLogLogic) FilterSubscribeLog(req *types.FilterSubscribeLogRequest) (resp *types.FilterSubscribeLogResponse, err error) {
|
||||
data, total, err := l.svcCtx.LogModel.FilterSystemLog(l.ctx, &log.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeSubscribe.Uint8(),
|
||||
Data: req.Date,
|
||||
ObjectID: req.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorf("[FilterSubscribeLog] failed to filter system log: %v", err.Error())
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "failed to filter system log")
|
||||
}
|
||||
|
||||
var list []types.SubscribeLog
|
||||
for _, datum := range data {
|
||||
var content log.Subscribe
|
||||
err = content.Unmarshal([]byte(datum.Content))
|
||||
if err != nil {
|
||||
l.Errorf("[FilterSubscribeLog] failed to unmarshal content: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.SubscribeLog{
|
||||
UserId: datum.ObjectID,
|
||||
Token: content.Token,
|
||||
UserAgent: content.UserAgent,
|
||||
ClientIP: content.ClientIP,
|
||||
UserSubscribeId: content.UserSubscribeId,
|
||||
SubscribedAt: datum.CreatedAt.UnixMilli(),
|
||||
})
|
||||
}
|
||||
|
||||
return &types.FilterSubscribeLogResponse{
|
||||
Total: total,
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type FilterUserSubscribeTrafficLogLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterUserSubscribeTrafficLogLogic Filter user subscribe traffic log
|
||||
func NewFilterUserSubscribeTrafficLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterUserSubscribeTrafficLogLogic {
|
||||
return &FilterUserSubscribeTrafficLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterUserSubscribeTrafficLogLogic) FilterUserSubscribeTrafficLog(req *types.FilterSubscribeTrafficRequest) (resp *types.FilterSubscribeTrafficResponse, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
@@ -2,18 +2,13 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/model/server"
|
||||
"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"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
queue "github.com/perfect-panel/server/queue/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -23,6 +18,7 @@ type CreateNodeLogic struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewCreateNodeLogic Create Node
|
||||
func NewCreateNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateNodeLogic {
|
||||
return &CreateNodeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
@@ -32,97 +28,18 @@ func NewCreateNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Create
|
||||
}
|
||||
|
||||
func (l *CreateNodeLogic) CreateNode(req *types.CreateNodeRequest) error {
|
||||
config, err := json.Marshal(req.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
data := node.Node{
|
||||
Name: req.Name,
|
||||
Tags: tool.StringSliceToString(req.Tags),
|
||||
Port: req.Port,
|
||||
Address: req.Address,
|
||||
ServerId: req.ServerId,
|
||||
Protocol: req.Protocol,
|
||||
}
|
||||
var serverInfo server.Server
|
||||
tool.DeepCopy(&serverInfo, req)
|
||||
serverInfo.Config = string(config)
|
||||
nodeRelay, err := json.Marshal(req.RelayNode)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateNode] Marshal RelayNode Error: ", logger.Field("error", err.Error()))
|
||||
return err
|
||||
}
|
||||
if len(req.Tags) > 0 {
|
||||
serverInfo.Tags = strings.Join(req.Tags, ",")
|
||||
}
|
||||
|
||||
serverInfo.LastReportedAt = time.UnixMicro(1218124800)
|
||||
|
||||
serverInfo.City = req.City
|
||||
serverInfo.Country = req.Country
|
||||
|
||||
serverInfo.RelayNode = string(nodeRelay)
|
||||
if req.Protocol == "vless" {
|
||||
var cfg types.Vless
|
||||
if err = json.Unmarshal(config, &cfg); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
if cfg.Security == "reality" && cfg.SecurityConfig.RealityPublicKey == "" {
|
||||
public, private, err := tool.Curve25519Genkey(false, "")
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "generate curve25519 key error")
|
||||
}
|
||||
cfg.SecurityConfig.RealityPublicKey = public
|
||||
cfg.SecurityConfig.RealityPrivateKey = private
|
||||
cfg.SecurityConfig.RealityShortId = tool.GenerateShortID(private)
|
||||
}
|
||||
if cfg.SecurityConfig.RealityServerAddr == "" {
|
||||
cfg.SecurityConfig.RealityServerAddr = cfg.SecurityConfig.SNI
|
||||
}
|
||||
if cfg.SecurityConfig.RealityServerPort == 0 {
|
||||
cfg.SecurityConfig.RealityServerPort = 443
|
||||
}
|
||||
config, _ = json.Marshal(cfg)
|
||||
serverInfo.Config = string(config)
|
||||
} else if req.Protocol == "shadowsocks" {
|
||||
var cfg types.Shadowsocks
|
||||
if err = json.Unmarshal(config, &cfg); err != nil {
|
||||
l.Errorf("[CreateNode] Unmarshal Shadowsocks Config Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
if strings.Contains(cfg.Method, "2022") {
|
||||
var length int
|
||||
switch cfg.Method {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
length = 16
|
||||
default:
|
||||
length = 32
|
||||
}
|
||||
if len(cfg.ServerKey) != length {
|
||||
cfg.ServerKey = tool.GenerateCipher(cfg.ServerKey, length)
|
||||
}
|
||||
}
|
||||
config, _ = json.Marshal(cfg)
|
||||
serverInfo.Config = string(config)
|
||||
}
|
||||
|
||||
err = l.svcCtx.ServerModel.Insert(l.ctx, &serverInfo)
|
||||
err := l.svcCtx.NodeModel.InsertNode(l.ctx, &data)
|
||||
if err != nil {
|
||||
l.Errorw("[CreateNode] Insert Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create server error: %v", err)
|
||||
}
|
||||
|
||||
if req.City == "" || req.Country == "" {
|
||||
// Marshal the task payload
|
||||
payload, err := json.Marshal(queue.GetNodeCountry{
|
||||
Protocol: serverInfo.Protocol,
|
||||
ServerAddr: serverInfo.ServerAddr,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[GetNodeCountry]: Marshal Error", logger.Field("error", err.Error()))
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.ERROR), "Failed to marshal task payload")
|
||||
}
|
||||
// Create a queue task
|
||||
task := asynq.NewTask(queue.ForthwithGetCountry, payload)
|
||||
// Enqueue the task
|
||||
taskInfo, err := l.svcCtx.Queue.Enqueue(task)
|
||||
if err != nil {
|
||||
l.Errorw("[GetNodeCountry]: Enqueue Error", logger.Field("error", err.Error()), logger.Field("payload", string(payload)))
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.ERROR), "Failed to enqueue task")
|
||||
}
|
||||
l.Infow("[GetNodeCountry]: Enqueue Success", logger.Field("taskID", taskInfo.ID), logger.Field("payload", string(payload)))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "[CreateNode] Insert Database Error")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"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/ip"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type CreateServerLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewCreateServerLogic Create Server
|
||||
func NewCreateServerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateServerLogic {
|
||||
return &CreateServerLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateServerLogic) CreateServer(req *types.CreateServerRequest) error {
|
||||
data := node.Server{
|
||||
Name: req.Name,
|
||||
Country: req.Country,
|
||||
City: req.City,
|
||||
Ratio: req.Ratio,
|
||||
Address: req.Address,
|
||||
Sort: req.Sort,
|
||||
Protocols: "",
|
||||
}
|
||||
protocols := make([]node.Protocol, 0)
|
||||
for _, item := range req.Protocols {
|
||||
if item.Type == "" {
|
||||
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.InvalidParams, "protocols type is empty"), "protocols type is empty")
|
||||
}
|
||||
var protocol node.Protocol
|
||||
tool.DeepCopy(&protocol, item)
|
||||
|
||||
// VLESS Reality Key Generation
|
||||
if protocol.Type == "vless" {
|
||||
if protocol.Security == "reality" {
|
||||
if protocol.RealityPublicKey == "" {
|
||||
public, private, err := tool.Curve25519Genkey(false, "")
|
||||
if err != nil {
|
||||
l.Errorf("[CreateServer] Generate Reality Key Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "generate reality key error: %v", err)
|
||||
}
|
||||
protocol.RealityPublicKey = public
|
||||
protocol.RealityPrivateKey = private
|
||||
protocol.RealityShortId = tool.GenerateShortID(private)
|
||||
}
|
||||
if protocol.RealityServerAddr == "" {
|
||||
protocol.RealityServerAddr = protocol.SNI
|
||||
}
|
||||
if protocol.RealityServerPort == 0 {
|
||||
protocol.RealityServerPort = 443
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// ShadowSocks 2022 Key Generation
|
||||
if protocol.Type == "shadowsocks" {
|
||||
if strings.Contains(protocol.Cipher, "2022") {
|
||||
var length int
|
||||
switch protocol.Cipher {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
length = 16
|
||||
default:
|
||||
length = 32
|
||||
}
|
||||
if len(protocol.ServerKey) != length {
|
||||
protocol.ServerKey = tool.GenerateCipher(protocol.ServerKey, length)
|
||||
}
|
||||
}
|
||||
}
|
||||
protocols = append(protocols, protocol)
|
||||
}
|
||||
|
||||
err := data.MarshalProtocols(protocols)
|
||||
if err != nil {
|
||||
l.Errorf("[CreateServer] Marshal Protocols Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.InvalidParams, "protocols marshal error"), "protocols marshal error: %v", err)
|
||||
}
|
||||
if data.City == "" && data.Country == "" {
|
||||
// query server ip location
|
||||
result, err := ip.GetRegionByIp(req.Address)
|
||||
if err != nil {
|
||||
l.Errorf("[CreateServer] GetRegionByIp Error: %v", err.Error())
|
||||
} else {
|
||||
data.City = result.City
|
||||
data.Country = result.Country
|
||||
}
|
||||
}
|
||||
err = l.svcCtx.NodeModel.InsertServer(l.ctx, &data)
|
||||
if err != nil {
|
||||
l.Errorf("[CreateServer] Insert Server error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "insert server error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -2,14 +2,12 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
|
||||
"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"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DeleteNodeLogic struct {
|
||||
@@ -18,6 +16,7 @@ type DeleteNodeLogic struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewDeleteNodeLogic Delete Node
|
||||
func NewDeleteNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteNodeLogic {
|
||||
return &DeleteNodeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
@@ -27,33 +26,10 @@ func NewDeleteNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Delete
|
||||
}
|
||||
|
||||
func (l *DeleteNodeLogic) DeleteNode(req *types.DeleteNodeRequest) error {
|
||||
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
|
||||
// Delete server
|
||||
err := l.svcCtx.ServerModel.Delete(l.ctx, req.Id, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Delete server to subscribe
|
||||
subs, err := l.svcCtx.SubscribeModel.QuerySubscribeIdsByServerIdAndServerGroupId(l.ctx, req.Id, 0)
|
||||
if err != nil {
|
||||
l.Logger.Errorf("[DeleteNode] QuerySubscribeIdsByServerIdAndServerGroupId error: %v", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
for _, sub := range subs {
|
||||
servers := tool.StringToInt64Slice(sub.Server)
|
||||
newServers := tool.RemoveElementBySlice(servers, req.Id)
|
||||
sub.Server = tool.Int64SliceToString(newServers)
|
||||
if err = l.svcCtx.SubscribeModel.Update(l.ctx, sub, tx); err != nil {
|
||||
l.Logger.Errorf("[DeleteNode] UpdateSubscribe error: %v", err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
err := l.svcCtx.NodeModel.DeleteNode(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
l.Errorw("[DeleteNode] Delete Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "delete server error: %v", err)
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "[DeleteNode] Delete Database Error")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type DeleteServerLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewDeleteServerLogic Delete Server
|
||||
func NewDeleteServerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteServerLogic {
|
||||
return &DeleteServerLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *DeleteServerLogic) DeleteServer(req *types.DeleteServerRequest) error {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type FilterNodeListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterNodeListLogic Filter Node List
|
||||
func NewFilterNodeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterNodeListLogic {
|
||||
return &FilterNodeListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterNodeListLogic) FilterNodeList(req *types.FilterNodeListRequest) (resp *types.FilterNodeListResponse, err error) {
|
||||
total, data, err := l.svcCtx.NodeModel.FilterNodeList(l.ctx, &node.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Search: req.Search,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorw("[FilterNodeList] Query Database Error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "[FilterNodeList] Query Database Error")
|
||||
}
|
||||
|
||||
list := make([]types.Node, 0)
|
||||
tool.DeepCopy(&list, data)
|
||||
|
||||
return &types.FilterNodeListResponse{
|
||||
List: list,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type FilterServerListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewFilterServerListLogic Filter Server List
|
||||
func NewFilterServerListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FilterServerListLogic {
|
||||
return &FilterServerListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FilterServerListLogic) FilterServerList(req *types.FilterServerListRequest) (resp *types.FilterServerListResponse, err error) {
|
||||
total, data, err := l.svcCtx.NodeModel.FilterServerList(l.ctx, &node.FilterParams{
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Search: req.Search,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[FilterServerList] Query Database Error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "[FilterServerList] Query Database Error")
|
||||
}
|
||||
|
||||
list := make([]types.Server, 0)
|
||||
|
||||
for _, datum := range data {
|
||||
var server types.Server
|
||||
tool.DeepCopy(&server, datum)
|
||||
|
||||
// handler protocols
|
||||
var protocols []types.Protocol
|
||||
dst, err := datum.UnmarshalProtocols()
|
||||
if err != nil {
|
||||
l.Errorf("[FilterServerList] UnmarshalProtocols Error: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
tool.DeepCopy(&protocols, dst)
|
||||
server.Protocols = protocols
|
||||
// handler status
|
||||
server.Status = l.handlerServerStatus(datum.Id)
|
||||
list = append(list, server)
|
||||
}
|
||||
|
||||
return &types.FilterServerListResponse{
|
||||
List: list,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
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))
|
||||
return result
|
||||
}
|
||||
result = types.ServerStatus{
|
||||
Mem: nodeStatus.Mem,
|
||||
Cpu: nodeStatus.Cpu,
|
||||
Disk: nodeStatus.Disk,
|
||||
Online: make([]types.ServerOnlineUser, 0),
|
||||
}
|
||||
|
||||
// parse online users
|
||||
onlineUser, err := l.svcCtx.NodeCache.GetNodeOnlineUser(l.ctx, id)
|
||||
if err != nil {
|
||||
l.Errorw("[handlerServerStatus] GetNodeOnlineUser Error: ", logger.Field("error", err.Error()), logger.Field("node_id", id))
|
||||
return result
|
||||
}
|
||||
|
||||
var onlineList []types.ServerOnlineUser
|
||||
var onlineMap = make(map[int64]types.ServerOnlineUser)
|
||||
// group by user_id
|
||||
for subId, info := range onlineUser {
|
||||
data, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, subId)
|
||||
if err != nil {
|
||||
l.Errorw("[handlerServerStatus] FindOneSubscribe Error: ", logger.Field("error", err.Error()))
|
||||
continue
|
||||
}
|
||||
if online, exist := onlineMap[data.UserId]; !exist {
|
||||
onlineMap[data.UserId] = types.ServerOnlineUser{
|
||||
IP: info,
|
||||
UserId: data.UserId,
|
||||
Subscribe: data.Subscribe.Name,
|
||||
SubscribeId: data.SubscribeId,
|
||||
Traffic: data.Traffic,
|
||||
ExpiredAt: data.ExpireTime.UnixMilli(),
|
||||
}
|
||||
} else {
|
||||
online.IP = append(online.IP, info...)
|
||||
onlineMap[data.UserId] = online
|
||||
}
|
||||
}
|
||||
|
||||
for _, online := range onlineMap {
|
||||
onlineList = append(onlineList, online)
|
||||
}
|
||||
|
||||
result.Online = onlineList
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type GetServerProtocolsLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get Server Protocols
|
||||
func NewGetServerProtocolsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetServerProtocolsLogic {
|
||||
return &GetServerProtocolsLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetServerProtocolsLogic) GetServerProtocols(req *types.GetServerProtocolsRequest) (resp *types.GetServerProtocolsResponse, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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 ToggleNodeStatusLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewToggleNodeStatusLogic Toggle Node Status
|
||||
func NewToggleNodeStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ToggleNodeStatusLogic {
|
||||
return &ToggleNodeStatusLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ToggleNodeStatusLogic) ToggleNodeStatus(req *types.ToggleNodeStatusRequest) error {
|
||||
data, err := l.svcCtx.NodeModel.FindOneNode(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
l.Errorw("[ToggleNodeStatus] Query Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "[ToggleNodeStatus] Query Database Error")
|
||||
}
|
||||
data.Enabled = req.Enable
|
||||
|
||||
err = l.svcCtx.NodeModel.UpdateNode(l.ctx, data)
|
||||
if err != nil {
|
||||
l.Errorw("[ToggleNodeStatus] Update Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "[ToggleNodeStatus] Update Database Error")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -2,12 +2,6 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/pkg/device"
|
||||
queue "github.com/perfect-panel/server/queue/types"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
@@ -23,6 +17,7 @@ type UpdateNodeLogic struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewUpdateNodeLogic Update Node
|
||||
func NewUpdateNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateNodeLogic {
|
||||
return &UpdateNodeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
@@ -32,108 +27,20 @@ func NewUpdateNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Update
|
||||
}
|
||||
|
||||
func (l *UpdateNodeLogic) UpdateNode(req *types.UpdateNodeRequest) error {
|
||||
// Check server exist
|
||||
nodeInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.Id)
|
||||
data, err := l.svcCtx.NodeModel.FindOneNode(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find server error: %v", err)
|
||||
l.Errorw("[UpdateNode] Query Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "[UpdateNode] Query Database Error")
|
||||
}
|
||||
tool.DeepCopy(nodeInfo, req, tool.CopyWithIgnoreEmpty(false))
|
||||
config, err := json.Marshal(req.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeInfo.Config = string(config)
|
||||
nodeRelay, err := json.Marshal(req.RelayNode)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateNode] Marshal RelayNode Error: ", logger.Field("error", err.Error()))
|
||||
return err
|
||||
}
|
||||
|
||||
// 处理Tags字段
|
||||
switch {
|
||||
case len(req.Tags) > 0:
|
||||
// 有Tags,进行连接
|
||||
nodeInfo.Tags = strings.Join(req.Tags, ",")
|
||||
default:
|
||||
// 空数组,清空Tags
|
||||
nodeInfo.Tags = ""
|
||||
}
|
||||
|
||||
nodeInfo.City = req.City
|
||||
nodeInfo.Country = req.Country
|
||||
|
||||
nodeInfo.RelayNode = string(nodeRelay)
|
||||
if req.Protocol == "vless" {
|
||||
var cfg types.Vless
|
||||
if err := json.Unmarshal(config, &cfg); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
if cfg.Security == "reality" && cfg.SecurityConfig.RealityPublicKey == "" {
|
||||
public, private, err := tool.Curve25519Genkey(false, "")
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "generate curve25519 key error")
|
||||
}
|
||||
cfg.SecurityConfig.RealityPublicKey = public
|
||||
cfg.SecurityConfig.RealityPrivateKey = private
|
||||
cfg.SecurityConfig.RealityShortId = tool.GenerateShortID(private)
|
||||
}
|
||||
if cfg.SecurityConfig.RealityServerAddr == "" {
|
||||
cfg.SecurityConfig.RealityServerAddr = cfg.SecurityConfig.SNI
|
||||
}
|
||||
if cfg.SecurityConfig.RealityServerPort == 0 {
|
||||
cfg.SecurityConfig.RealityServerPort = 443
|
||||
}
|
||||
config, _ = json.Marshal(cfg)
|
||||
nodeInfo.Config = string(config)
|
||||
} else if req.Protocol == "shadowsocks" {
|
||||
var cfg types.Shadowsocks
|
||||
if err = json.Unmarshal(config, &cfg); err != nil {
|
||||
l.Errorf("[CreateNode] Unmarshal Shadowsocks Config Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
if strings.Contains(cfg.Method, "2022") {
|
||||
var length int
|
||||
switch cfg.Method {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
length = 16
|
||||
default:
|
||||
length = 32
|
||||
}
|
||||
if len(cfg.ServerKey) != length {
|
||||
cfg.ServerKey = tool.GenerateCipher(cfg.ServerKey, length)
|
||||
}
|
||||
}
|
||||
config, _ = json.Marshal(cfg)
|
||||
nodeInfo.Config = string(config)
|
||||
}
|
||||
err = l.svcCtx.ServerModel.Update(l.ctx, nodeInfo)
|
||||
data.Name = req.Name
|
||||
data.Tags = tool.StringSliceToString(req.Tags)
|
||||
data.Port = req.Port
|
||||
data.Address = req.Address
|
||||
data.Protocol = req.Protocol
|
||||
err = l.svcCtx.NodeModel.UpdateNode(l.ctx, data)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateNode] Update Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create server error: %v", err)
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "[UpdateNode] Update Database Error")
|
||||
}
|
||||
|
||||
if req.City == "" || req.Country == "" {
|
||||
// Marshal the task payload
|
||||
payload, err := json.Marshal(queue.GetNodeCountry{
|
||||
Protocol: nodeInfo.Protocol,
|
||||
ServerAddr: nodeInfo.ServerAddr,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[GetNodeCountry]: Marshal Error", logger.Field("error", err.Error()))
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.ERROR), "Failed to marshal task payload")
|
||||
}
|
||||
// Create a queue task
|
||||
task := asynq.NewTask(queue.ForthwithGetCountry, payload)
|
||||
// Enqueue the task
|
||||
taskInfo, err := l.svcCtx.Queue.Enqueue(task)
|
||||
if err != nil {
|
||||
l.Errorw("[GetNodeCountry]: Enqueue Error", logger.Field("error", err.Error()), logger.Field("payload", string(payload)))
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.ERROR), "Failed to enqueue task")
|
||||
}
|
||||
l.Infow("[GetNodeCountry]: Enqueue Success", logger.Field("taskID", taskInfo.ID), logger.Field("payload", string(payload)))
|
||||
}
|
||||
|
||||
l.svcCtx.DeviceManager.Broadcast(device.SubscribeUpdate)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"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/ip"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type UpdateServerLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewUpdateServerLogic Update Server
|
||||
func NewUpdateServerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateServerLogic {
|
||||
return &UpdateServerLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UpdateServerLogic) UpdateServer(req *types.UpdateServerRequest) error {
|
||||
data, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
l.Errorf("[UpdateServer] FindOneServer Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find server error: %v", err.Error())
|
||||
}
|
||||
data.Name = req.Name
|
||||
data.Country = req.Country
|
||||
data.City = req.City
|
||||
data.Ratio = req.Ratio
|
||||
// only update address when it's different
|
||||
if req.Address != data.Address {
|
||||
// query server ip location
|
||||
result, err := ip.GetRegionByIp(req.Address)
|
||||
if err != nil {
|
||||
l.Errorf("[UpdateServer] GetRegionByIp Error: %v", err.Error())
|
||||
} else {
|
||||
data.City = result.City
|
||||
data.Country = result.Country
|
||||
}
|
||||
// update address
|
||||
data.Address = req.Address
|
||||
}
|
||||
protocols := make([]node.Protocol, 0)
|
||||
for _, item := range req.Protocols {
|
||||
if item.Type == "" {
|
||||
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.InvalidParams, "protocols type is empty"), "protocols type is empty")
|
||||
}
|
||||
var protocol node.Protocol
|
||||
tool.DeepCopy(&protocol, item)
|
||||
|
||||
// VLESS Reality Key Generation
|
||||
if protocol.Type == "vless" {
|
||||
if protocol.Security == "reality" {
|
||||
if protocol.RealityPublicKey == "" {
|
||||
public, private, err := tool.Curve25519Genkey(false, "")
|
||||
if err != nil {
|
||||
l.Errorf("[CreateServer] Generate Reality Key Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "generate reality key error: %v", err)
|
||||
}
|
||||
protocol.RealityPublicKey = public
|
||||
protocol.RealityPrivateKey = private
|
||||
protocol.RealityShortId = tool.GenerateShortID(private)
|
||||
}
|
||||
if protocol.RealityServerAddr == "" {
|
||||
protocol.RealityServerAddr = protocol.SNI
|
||||
}
|
||||
if protocol.RealityServerPort == 0 {
|
||||
protocol.RealityServerPort = 443
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// ShadowSocks 2022 Key Generation
|
||||
if protocol.Type == "shadowsocks" {
|
||||
if strings.Contains(protocol.Cipher, "2022") {
|
||||
var length int
|
||||
switch protocol.Cipher {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
length = 16
|
||||
default:
|
||||
length = 32
|
||||
}
|
||||
if len(protocol.ServerKey) != length {
|
||||
protocol.ServerKey = tool.GenerateCipher(protocol.ServerKey, length)
|
||||
}
|
||||
}
|
||||
}
|
||||
protocols = append(protocols, protocol)
|
||||
}
|
||||
err = data.MarshalProtocols(protocols)
|
||||
if err != nil {
|
||||
l.Errorf("[UpdateServer] Marshal Protocols Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.InvalidParams, "protocols marshal error"), "protocols marshal error: %v", err)
|
||||
}
|
||||
|
||||
err = l.svcCtx.NodeModel.UpdateServer(l.ctx, data)
|
||||
if err != nil {
|
||||
l.Errorf("[UpdateServer] UpdateServer Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update server error: %v", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -0,0 +1,129 @@
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"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/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
queue "github.com/perfect-panel/server/queue/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type CreateNodeLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCreateNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateNodeLogic {
|
||||
return &CreateNodeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateNodeLogic) CreateNode(req *types.CreateNodeRequest) error {
|
||||
config, err := json.Marshal(req.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var serverInfo server.Server
|
||||
tool.DeepCopy(&serverInfo, req)
|
||||
serverInfo.Config = string(config)
|
||||
nodeRelay, err := json.Marshal(req.RelayNode)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateNode] Marshal RelayNode Error: ", logger.Field("error", err.Error()))
|
||||
return err
|
||||
}
|
||||
if len(req.Tags) > 0 {
|
||||
serverInfo.Tags = strings.Join(req.Tags, ",")
|
||||
}
|
||||
|
||||
serverInfo.LastReportedAt = time.UnixMicro(1218124800)
|
||||
|
||||
serverInfo.City = req.City
|
||||
serverInfo.Country = req.Country
|
||||
|
||||
serverInfo.RelayNode = string(nodeRelay)
|
||||
if req.Protocol == "vless" {
|
||||
var cfg types.Vless
|
||||
if err = json.Unmarshal(config, &cfg); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
if cfg.Security == "reality" && cfg.SecurityConfig.RealityPublicKey == "" {
|
||||
public, private, err := tool.Curve25519Genkey(false, "")
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "generate curve25519 key error")
|
||||
}
|
||||
cfg.SecurityConfig.RealityPublicKey = public
|
||||
cfg.SecurityConfig.RealityPrivateKey = private
|
||||
cfg.SecurityConfig.RealityShortId = tool.GenerateShortID(private)
|
||||
}
|
||||
if cfg.SecurityConfig.RealityServerAddr == "" {
|
||||
cfg.SecurityConfig.RealityServerAddr = cfg.SecurityConfig.SNI
|
||||
}
|
||||
if cfg.SecurityConfig.RealityServerPort == 0 {
|
||||
cfg.SecurityConfig.RealityServerPort = 443
|
||||
}
|
||||
config, _ = json.Marshal(cfg)
|
||||
serverInfo.Config = string(config)
|
||||
} else if req.Protocol == "shadowsocks" {
|
||||
var cfg types.Shadowsocks
|
||||
if err = json.Unmarshal(config, &cfg); err != nil {
|
||||
l.Errorf("[CreateNode] Unmarshal Shadowsocks Config Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
if strings.Contains(cfg.Method, "2022") {
|
||||
var length int
|
||||
switch cfg.Method {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
length = 16
|
||||
default:
|
||||
length = 32
|
||||
}
|
||||
if len(cfg.ServerKey) != length {
|
||||
cfg.ServerKey = tool.GenerateCipher(cfg.ServerKey, length)
|
||||
}
|
||||
}
|
||||
config, _ = json.Marshal(cfg)
|
||||
serverInfo.Config = string(config)
|
||||
}
|
||||
|
||||
err = l.svcCtx.ServerModel.Insert(l.ctx, &serverInfo)
|
||||
if err != nil {
|
||||
l.Errorw("[CreateNode] Insert Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create server error: %v", err)
|
||||
}
|
||||
|
||||
if req.City == "" || req.Country == "" {
|
||||
// Marshal the task payload
|
||||
payload, err := json.Marshal(queue.GetNodeCountry{
|
||||
Protocol: serverInfo.Protocol,
|
||||
ServerAddr: serverInfo.ServerAddr,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[GetNodeCountry]: Marshal Error", logger.Field("error", err.Error()))
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.ERROR), "Failed to marshal task payload")
|
||||
}
|
||||
// Create a queue task
|
||||
task := asynq.NewTask(queue.ForthwithGetCountry, payload)
|
||||
// Enqueue the task
|
||||
taskInfo, err := l.svcCtx.Queue.Enqueue(task)
|
||||
if err != nil {
|
||||
l.Errorw("[GetNodeCountry]: Enqueue Error", logger.Field("error", err.Error()), logger.Field("payload", string(payload)))
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.ERROR), "Failed to enqueue task")
|
||||
}
|
||||
l.Infow("[GetNodeCountry]: Enqueue Success", logger.Field("taskID", taskInfo.ID), logger.Field("payload", string(payload)))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -0,0 +1,59 @@
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
|
||||
"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"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DeleteNodeLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewDeleteNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteNodeLogic {
|
||||
return &DeleteNodeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *DeleteNodeLogic) DeleteNode(req *types.DeleteNodeRequest) error {
|
||||
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
|
||||
// Delete server
|
||||
err := l.svcCtx.ServerModel.Delete(l.ctx, req.Id, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Delete server to subscribe
|
||||
subs, err := l.svcCtx.SubscribeModel.QuerySubscribeIdsByServerIdAndServerGroupId(l.ctx, req.Id, 0)
|
||||
if err != nil {
|
||||
l.Logger.Errorf("[DeleteNode] QuerySubscribeIdsByServerIdAndServerGroupId error: %v", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
for _, sub := range subs {
|
||||
servers := tool.StringToInt64Slice(sub.Server)
|
||||
newServers := tool.RemoveElementBySlice(servers, req.Id)
|
||||
sub.Server = tool.Int64SliceToString(newServers)
|
||||
if err = l.svcCtx.SubscribeModel.Update(l.ctx, sub, tx); err != nil {
|
||||
l.Logger.Errorf("[DeleteNode] UpdateSubscribe error: %v", err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[DeleteNode] Delete Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "delete server error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -0,0 +1,139 @@
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/pkg/device"
|
||||
queue "github.com/perfect-panel/server/queue/types"
|
||||
|
||||
"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/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type UpdateNodeLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewUpdateNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateNodeLogic {
|
||||
return &UpdateNodeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UpdateNodeLogic) UpdateNode(req *types.UpdateNodeRequest) error {
|
||||
// Check server exist
|
||||
nodeInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find server error: %v", err)
|
||||
}
|
||||
tool.DeepCopy(nodeInfo, req, tool.CopyWithIgnoreEmpty(false))
|
||||
config, err := json.Marshal(req.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeInfo.Config = string(config)
|
||||
nodeRelay, err := json.Marshal(req.RelayNode)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateNode] Marshal RelayNode Error: ", logger.Field("error", err.Error()))
|
||||
return err
|
||||
}
|
||||
|
||||
// 处理Tags字段
|
||||
switch {
|
||||
case len(req.Tags) > 0:
|
||||
// 有Tags,进行连接
|
||||
nodeInfo.Tags = strings.Join(req.Tags, ",")
|
||||
default:
|
||||
// 空数组,清空Tags
|
||||
nodeInfo.Tags = ""
|
||||
}
|
||||
|
||||
nodeInfo.City = req.City
|
||||
nodeInfo.Country = req.Country
|
||||
|
||||
nodeInfo.RelayNode = string(nodeRelay)
|
||||
if req.Protocol == "vless" {
|
||||
var cfg types.Vless
|
||||
if err := json.Unmarshal(config, &cfg); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
if cfg.Security == "reality" && cfg.SecurityConfig.RealityPublicKey == "" {
|
||||
public, private, err := tool.Curve25519Genkey(false, "")
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "generate curve25519 key error")
|
||||
}
|
||||
cfg.SecurityConfig.RealityPublicKey = public
|
||||
cfg.SecurityConfig.RealityPrivateKey = private
|
||||
cfg.SecurityConfig.RealityShortId = tool.GenerateShortID(private)
|
||||
}
|
||||
if cfg.SecurityConfig.RealityServerAddr == "" {
|
||||
cfg.SecurityConfig.RealityServerAddr = cfg.SecurityConfig.SNI
|
||||
}
|
||||
if cfg.SecurityConfig.RealityServerPort == 0 {
|
||||
cfg.SecurityConfig.RealityServerPort = 443
|
||||
}
|
||||
config, _ = json.Marshal(cfg)
|
||||
nodeInfo.Config = string(config)
|
||||
} else if req.Protocol == "shadowsocks" {
|
||||
var cfg types.Shadowsocks
|
||||
if err = json.Unmarshal(config, &cfg); err != nil {
|
||||
l.Errorf("[CreateNode] Unmarshal Shadowsocks Config Error: %v", err.Error())
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
if strings.Contains(cfg.Method, "2022") {
|
||||
var length int
|
||||
switch cfg.Method {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
length = 16
|
||||
default:
|
||||
length = 32
|
||||
}
|
||||
if len(cfg.ServerKey) != length {
|
||||
cfg.ServerKey = tool.GenerateCipher(cfg.ServerKey, length)
|
||||
}
|
||||
}
|
||||
config, _ = json.Marshal(cfg)
|
||||
nodeInfo.Config = string(config)
|
||||
}
|
||||
err = l.svcCtx.ServerModel.Update(l.ctx, nodeInfo)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateNode] Update Database Error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create server error: %v", err)
|
||||
}
|
||||
|
||||
if req.City == "" || req.Country == "" {
|
||||
// Marshal the task payload
|
||||
payload, err := json.Marshal(queue.GetNodeCountry{
|
||||
Protocol: nodeInfo.Protocol,
|
||||
ServerAddr: nodeInfo.ServerAddr,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[GetNodeCountry]: Marshal Error", logger.Field("error", err.Error()))
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.ERROR), "Failed to marshal task payload")
|
||||
}
|
||||
// Create a queue task
|
||||
task := asynq.NewTask(queue.ForthwithGetCountry, payload)
|
||||
// Enqueue the task
|
||||
taskInfo, err := l.svcCtx.Queue.Enqueue(task)
|
||||
if err != nil {
|
||||
l.Errorw("[GetNodeCountry]: Enqueue Error", logger.Field("error", err.Error()), logger.Field("payload", string(payload)))
|
||||
return errors.Wrap(xerr.NewErrCode(xerr.ERROR), "Failed to enqueue task")
|
||||
}
|
||||
l.Infow("[GetNodeCountry]: Enqueue Success", logger.Field("taskID", taskInfo.ID), logger.Field("payload", string(payload)))
|
||||
}
|
||||
|
||||
l.svcCtx.DeviceManager.Broadcast(device.SubscribeUpdate)
|
||||
return nil
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package server_bak
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -65,7 +65,7 @@ func (l *OAuthLoginGetTokenLogic) OAuthLoginGetToken(req *types.OAuthLoginGetTok
|
||||
)
|
||||
|
||||
defer func() {
|
||||
l.recordLoginStatus(loginStatus, userInfo, ip, userAgent, requestID)
|
||||
l.recordLoginStatus(loginStatus, userInfo, ip, userAgent, requestID, req.Method)
|
||||
}()
|
||||
|
||||
userInfo, err = l.handleOAuthProvider(req, requestID)
|
||||
@@ -487,10 +487,11 @@ func (l *OAuthLoginGetTokenLogic) createAuthMethod(db *gorm.DB, userID int64, au
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *OAuthLoginGetTokenLogic) recordLoginStatus(loginStatus bool, userInfo *user.User, ip, userAgent, requestID string) {
|
||||
func (l *OAuthLoginGetTokenLogic) recordLoginStatus(loginStatus bool, userInfo *user.User, ip, userAgent, requestID, authType string) {
|
||||
|
||||
if userInfo != nil && userInfo.Id != 0 {
|
||||
loginLog := log.Login{
|
||||
Method: authType,
|
||||
LoginIP: ip,
|
||||
UserAgent: userAgent,
|
||||
Success: loginStatus,
|
||||
|
||||
@@ -45,6 +45,7 @@ func (l *ResetPasswordLogic) ResetPassword(req *types.ResetPasswordRequest) (res
|
||||
defer func() {
|
||||
if userInfo.Id != 0 && loginStatus {
|
||||
loginLog := log.Login{
|
||||
Method: "email",
|
||||
LoginIP: req.IP,
|
||||
UserAgent: req.UserAgent,
|
||||
Success: loginStatus,
|
||||
|
||||
@@ -53,6 +53,7 @@ func (l *TelephoneLoginLogic) TelephoneLogin(req *types.TelephoneLoginRequest, r
|
||||
defer func(svcCtx *svc.ServiceContext) {
|
||||
if userInfo.Id != 0 {
|
||||
loginLog := log.Login{
|
||||
Method: "mobile",
|
||||
LoginIP: ip,
|
||||
UserAgent: r.UserAgent(),
|
||||
Success: loginStatus,
|
||||
|
||||
@@ -104,6 +104,7 @@ func (l *TelephoneResetPasswordLogic) TelephoneResetPassword(req *types.Telephon
|
||||
defer func() {
|
||||
if token != "" && userInfo.Id != 0 {
|
||||
loginLog := log.Login{
|
||||
Method: "mobile",
|
||||
LoginIP: req.IP,
|
||||
UserAgent: req.UserAgent,
|
||||
Success: token != "",
|
||||
|
||||
@@ -159,6 +159,7 @@ func (l *TelephoneUserRegisterLogic) TelephoneUserRegister(req *types.TelephoneR
|
||||
defer func() {
|
||||
if token != "" && userInfo.Id != 0 {
|
||||
loginLog := log.Login{
|
||||
Method: "mobile",
|
||||
LoginIP: req.IP,
|
||||
UserAgent: req.UserAgent,
|
||||
Success: token != "",
|
||||
|
||||
@@ -43,6 +43,7 @@ func (l *UserLoginLogic) UserLogin(req *types.UserLoginRequest) (resp *types.Log
|
||||
defer func(svcCtx *svc.ServiceContext) {
|
||||
if userInfo.Id != 0 {
|
||||
loginLog := log.Login{
|
||||
Method: "email",
|
||||
LoginIP: req.IP,
|
||||
UserAgent: req.UserAgent,
|
||||
Success: loginStatus,
|
||||
|
||||
@@ -147,6 +147,7 @@ func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterRequest) (resp *
|
||||
defer func() {
|
||||
if token != "" && userInfo.Id != 0 {
|
||||
loginLog := log.Login{
|
||||
Method: "email",
|
||||
LoginIP: req.IP,
|
||||
UserAgent: req.UserAgent,
|
||||
Success: loginStatus,
|
||||
|
||||
@@ -20,7 +20,7 @@ type GetSubscribeLogLogic struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get Subscribe Log
|
||||
// NewGetSubscribeLogLogic Get Subscribe Log
|
||||
func NewGetSubscribeLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSubscribeLogLogic {
|
||||
return &GetSubscribeLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
@@ -39,7 +39,7 @@ func (l *GetSubscribeLogLogic) GetSubscribeLog(req *types.GetSubscribeLogRequest
|
||||
Page: req.Page,
|
||||
Size: req.Size,
|
||||
Type: log.TypeSubscribe.Uint8(),
|
||||
ObjectID: u.Id,
|
||||
ObjectID: u.Id, // filter by current user id
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[GetUserSubscribeLogs] Get User Subscribe Logs Error:", logger.Field("err", err.Error()))
|
||||
@@ -56,7 +56,7 @@ func (l *GetSubscribeLogLogic) GetSubscribeLog(req *types.GetSubscribeLogRequest
|
||||
list = append(list, types.UserSubscribeLog{
|
||||
Id: item.Id,
|
||||
UserId: item.ObjectID,
|
||||
UserSubscribeId: content.SubscribeId,
|
||||
UserSubscribeId: content.UserSubscribeId,
|
||||
Token: content.Token,
|
||||
IP: content.ClientIP,
|
||||
UserAgent: content.UserAgent,
|
||||
|
||||
@@ -20,7 +20,7 @@ type QueryUserBalanceLogLogic struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Query User Balance Log
|
||||
// NewQueryUserBalanceLogLogic Query User Balance Log
|
||||
func NewQueryUserBalanceLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryUserBalanceLogLogic {
|
||||
return &QueryUserBalanceLogLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
@@ -51,21 +51,20 @@ func (l *QueryUserBalanceLogLogic) QueryUserBalanceLog() (resp *types.QueryUserB
|
||||
Total: total,
|
||||
}
|
||||
|
||||
list := make([]types.UserBalanceLog, 0)
|
||||
list := make([]types.BalanceLog, 0)
|
||||
for _, datum := range data {
|
||||
var content log.Balance
|
||||
if err = content.Unmarshal([]byte(datum.Content)); err != nil {
|
||||
l.Errorf("[QueryUserBalanceLog] unmarshal balance log content failed: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
list = append(list, types.UserBalanceLog{
|
||||
Id: datum.Id,
|
||||
list = append(list, types.BalanceLog{
|
||||
UserId: datum.ObjectID,
|
||||
Amount: content.Amount,
|
||||
Type: content.Type,
|
||||
OrderId: content.OrderId,
|
||||
Balance: content.Balance,
|
||||
CreatedAt: datum.CreatedAt.UnixMilli(),
|
||||
Timestamp: content.Timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,10 @@ func (l *QueryUserCommissionLogLogic) QueryUserCommissionLog(req *types.QueryUse
|
||||
continue
|
||||
}
|
||||
list = append(list, types.CommissionLog{
|
||||
Id: datum.Id,
|
||||
UserId: datum.ObjectID,
|
||||
OrderNo: content.OrderNo,
|
||||
Type: content.Type,
|
||||
Amount: content.Amount,
|
||||
OrderNo: content.OrderNo,
|
||||
CreatedAt: content.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -177,16 +177,17 @@ func (l *SubscribeLogic) logSubscribeActivity(subscribeStatus bool, userSub *use
|
||||
}
|
||||
|
||||
subscribeLog := log.Subscribe{
|
||||
Token: req.Token,
|
||||
UserAgent: req.UA,
|
||||
ClientIP: l.ctx.ClientIP(),
|
||||
Token: req.Token,
|
||||
UserAgent: req.UA,
|
||||
ClientIP: l.ctx.ClientIP(),
|
||||
UserSubscribeId: userSub.Id,
|
||||
}
|
||||
|
||||
content, _ := subscribeLog.Marshal()
|
||||
|
||||
err := l.svc.LogModel.Insert(l.ctx.Request.Context(), &log.SystemLog{
|
||||
Type: log.TypeSubscribe.Uint8(),
|
||||
ObjectID: userSub.Id,
|
||||
ObjectID: userSub.UserId, // log user id
|
||||
Date: time.Now().Format(time.DateOnly),
|
||||
Content: string(content),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user