Merge upstream/master into develop

Sync upstream changes from perfect-panel/server

  Includes updates from v1.0.1 to v1.2.5:
  - Currency configuration support
  - Subscribe improvements (short token, inventory check, etc.)
  - Node management enhancements
  - Database migrations
  - Bug fixes and optimizations
This commit is contained in:
EUForest
2026-01-02 12:51:55 +08:00
parent 47c41d1d14
commit 80ee9a6acf
63 changed files with 947 additions and 1509 deletions
@@ -1,18 +0,0 @@
package server
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/admin/server"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/result"
)
// Check if there is any server or node to migrate
func HasMigrateSeverNodeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
l := server.NewHasMigrateSeverNodeLogic(c.Request.Context(), svcCtx)
resp, err := l.HasMigrateSeverNode()
result.HttpResult(c, resp, err)
}
}
@@ -1,18 +0,0 @@
package server
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/admin/server"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/result"
)
// Migrate server and node data to new database
func MigrateServerNodeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
l := server.NewMigrateServerNodeLogic(c.Request.Context(), svcCtx)
resp, err := l.MigrateServerNode()
result.HttpResult(c, resp, err)
}
}
@@ -0,0 +1,26 @@
package user
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/admin/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Reset user subscribe token
func ResetUserSubscribeTokenHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.ResetUserSubscribeTokenRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := user.NewResetUserSubscribeTokenLogic(c.Request.Context(), svcCtx)
err := l.ResetUserSubscribeToken(&req)
result.HttpResult(c, nil, err)
}
}
@@ -0,0 +1,26 @@
package user
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/admin/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Reset user subscribe traffic
func ResetUserSubscribeTrafficHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.ResetUserSubscribeTrafficRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := user.NewResetUserSubscribeTrafficLogic(c.Request.Context(), svcCtx)
err := l.ResetUserSubscribeTraffic(&req)
result.HttpResult(c, nil, err)
}
}
@@ -0,0 +1,26 @@
package user
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/admin/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Stop user subscribe
func ToggleUserSubscribeStatusHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.ToggleUserSubscribeStatusRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := user.NewToggleUserSubscribeStatusLogic(c.Request.Context(), svcCtx)
err := l.ToggleUserSubscribeStatus(&req)
result.HttpResult(c, nil, err)
}
}
+9 -15
View File
@@ -33,7 +33,6 @@ import (
publicSubscribe "github.com/perfect-panel/server/internal/handler/public/subscribe"
publicTicket "github.com/perfect-panel/server/internal/handler/public/ticket"
publicUser "github.com/perfect-panel/server/internal/handler/public/user"
publicUserWs "github.com/perfect-panel/server/internal/handler/public/user/ws"
server "github.com/perfect-panel/server/internal/handler/server"
"github.com/perfect-panel/server/internal/middleware"
"github.com/perfect-panel/server/internal/svc"
@@ -312,12 +311,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// Filter Server List
adminServerGroupRouter.GET("/list", adminServer.FilterServerListHandler(serverCtx))
// Check if there is any server or node to migrate
adminServerGroupRouter.GET("/migrate/has", adminServer.HasMigrateSeverNodeHandler(serverCtx))
// Migrate server and node data to new database
adminServerGroupRouter.POST("/migrate/run", adminServer.MigrateServerNodeHandler(serverCtx))
// Create Node
adminServerGroupRouter.POST("/node/create", adminServer.CreateNodeHandler(serverCtx))
@@ -583,6 +576,15 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// Get user subcribe reset traffic logs
adminUserGroupRouter.GET("/subscribe/reset/logs", adminUser.GetUserSubscribeResetTrafficLogsHandler(serverCtx))
// Reset user subscribe token
adminUserGroupRouter.POST("/subscribe/reset/token", adminUser.ResetUserSubscribeTokenHandler(serverCtx))
// Reset user subscribe traffic
adminUserGroupRouter.POST("/subscribe/reset/traffic", adminUser.ResetUserSubscribeTrafficHandler(serverCtx))
// Stop user subscribe
adminUserGroupRouter.POST("/subscribe/toggle", adminUser.ToggleUserSubscribeStatusHandler(serverCtx))
// Get user subcribe traffic logs
adminUserGroupRouter.GET("/subscribe/traffic_logs", adminUser.GetUserSubscribeTrafficLogsHandler(serverCtx))
}
@@ -872,14 +874,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
publicUserGroupRouter.GET("/withdrawal_log", publicUser.QueryWithdrawalLogHandler(serverCtx))
}
publicUserWsGroupRouter := router.Group("/v1/public/user")
publicUserWsGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Webosocket Device Connect
publicUserWsGroupRouter.GET("/device_ws_connect", publicUserWs.DeviceWsConnectHandler(serverCtx))
}
serverGroupRouter := router.Group("/v1/server")
serverGroupRouter.Use(middleware.ServerMiddleware(serverCtx))
+17 -1
View File
@@ -23,6 +23,10 @@ func SubscribeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
ua := c.GetHeader("User-Agent")
req.UA = c.Request.Header.Get("User-Agent")
req.Flag = c.Query("flag")
req.Type = c.Query("type")
// 获取所有查询参数
req.Params = getQueryMap(c.Request)
if svcCtx.Config.Subscribe.PanDomain {
domain := c.Request.Host
domainArr := strings.Split(domain, ".")
@@ -33,7 +37,8 @@ func SubscribeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
c.Abort()
return
}
if short != domainArr[0] {
if strings.ToLower(short) != strings.ToLower(domainArr[0]) {
logger.Debugf("[SubscribeHandler] Generate short token failed, short: %s, domain: %s", short, domainArr[0])
c.String(http.StatusForbidden, "Access denied")
c.Abort()
return
@@ -94,3 +99,14 @@ func RegisterSubscribeHandlers(router *gin.Engine, serverCtx *svc.ServiceContext
}
router.GET(path, SubscribeHandler(serverCtx))
}
// GetQueryMap 将 http.Request 的查询参数转换为 map[string]string
func getQueryMap(r *http.Request) map[string]string {
result := make(map[string]string)
for k, v := range r.URL.Query() {
if len(v) > 0 {
result[k] = v[0]
}
}
return result
}