同步历史版本代码
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
package apple
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
appleLogic "github.com/perfect-panel/server/internal/logic/public/iap/apple"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
func AttachAppleTransactionByIdHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AttachAppleTransactionByIdRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
if err := svcCtx.Validate(&req); err != nil {
|
||||
result.ParamErrorResult(c, err)
|
||||
return
|
||||
}
|
||||
l := appleLogic.NewAttachTransactionByIdLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.AttachById(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package apple
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
appleLogic "github.com/perfect-panel/server/internal/logic/public/iap/apple"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
func AttachAppleTransactionHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AttachAppleTransactionRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
if err := svcCtx.Validate(&req); err != nil {
|
||||
result.ParamErrorResult(c, err)
|
||||
return
|
||||
}
|
||||
l := appleLogic.NewAttachTransactionLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.Attach(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package apple
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
appleLogic "github.com/perfect-panel/server/internal/logic/public/iap/apple"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
func GetAppleStatusHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
l := appleLogic.NewGetStatusLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetStatus()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package apple
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
appleLogic "github.com/perfect-panel/server/internal/logic/public/iap/apple"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
func RestoreAppleTransactionsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.RestoreAppleTransactionsRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
if err := svcCtx.Validate(&req); err != nil {
|
||||
result.ParamErrorResult(c, err)
|
||||
return
|
||||
}
|
||||
l := appleLogic.NewRestoreLogic(c.Request.Context(), svcCtx)
|
||||
err := l.Restore(&req)
|
||||
result.HttpResult(c, map[string]bool{"success": err == nil}, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Bind Email With Verification
|
||||
func BindEmailWithVerificationHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.BindEmailWithVerificationRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewBindEmailWithVerificationLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.BindEmailWithVerification(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
logic "github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
func BindInviteCodeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.BindInviteCodeRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := logic.NewBindInviteCodeLogic(c.Request.Context(), svcCtx)
|
||||
err := l.BindInviteCode(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// DeleteAccountHandler 注销账号处理器
|
||||
// 根据当前token删除所有关联设备,然后根据各自设备ID重新新建账号
|
||||
// 新增:需携带邮箱验证码,验证通过后执行注销
|
||||
type deleteAccountReq struct {
|
||||
Email string `json:"email" binding:"required,email"` // 用户邮箱
|
||||
Code string `json:"code" binding:"required"` // 邮箱验证码
|
||||
}
|
||||
|
||||
func DeleteAccountHandler(serverCtx *svc.ServiceContext) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var req deleteAccountReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 统一处理邮箱格式:转小写并去空格,与发送验证码逻辑保持一致
|
||||
req.Email = strings.ToLower(strings.TrimSpace(req.Email))
|
||||
|
||||
// 校验邮箱验证码
|
||||
if err := verifyEmailCode(c.Request.Context(), serverCtx, req.Email, req.Code); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewDeleteAccountLogic(c.Request.Context(), serverCtx)
|
||||
resp, err := l.DeleteAccountAll()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
result.HttpResult(c, resp, err)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// CacheKeyPayload 验证码缓存结构
|
||||
type CacheKeyPayload struct {
|
||||
Code string `json:"code"`
|
||||
LastAt int64 `json:"lastAt"`
|
||||
}
|
||||
|
||||
// verifyEmailCode 校验邮箱验证码
|
||||
// 支持 DeleteAccount 和 Security 两种场景的验证码
|
||||
func verifyEmailCode(ctx context.Context, serverCtx *svc.ServiceContext, email string, code string) error {
|
||||
// 尝试多种场景的验证码
|
||||
scenes := []string{constant.DeleteAccount.String(), constant.Security.String()}
|
||||
var verified bool
|
||||
var cacheKeyUsed string
|
||||
var payload CacheKeyPayload
|
||||
|
||||
for _, scene := range scenes {
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeCacheKey, scene, email)
|
||||
value, err := serverCtx.Redis.Get(ctx, cacheKey).Result()
|
||||
if err != nil || value == "" {
|
||||
continue
|
||||
}
|
||||
if err := json.Unmarshal([]byte(value), &payload); err != nil {
|
||||
continue
|
||||
}
|
||||
// 检查验证码是否匹配且未过期
|
||||
if payload.Code == code && time.Now().Unix()-payload.LastAt <= serverCtx.Config.VerifyCode.ExpireTime {
|
||||
verified = true
|
||||
cacheKeyUsed = cacheKey
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !verified {
|
||||
return fmt.Errorf("verification code error or expired")
|
||||
}
|
||||
|
||||
// 验证成功后删除缓存
|
||||
serverCtx.Redis.Del(ctx, cacheKeyUsed)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get agent downloads data
|
||||
func GetAgentDownloadsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.GetAgentDownloadsRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewGetAgentDownloadsLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetAgentDownloads(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get agent realtime data
|
||||
func GetAgentRealtimeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.GetAgentRealtimeRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewGetAgentRealtimeLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetAgentRealtime(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get invite sales data
|
||||
func GetInviteSalesHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.GetInviteSalesRequest
|
||||
if err := c.ShouldBind(&req); err != nil {
|
||||
result.ParamErrorResult(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewGetInviteSalesLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetInviteSales(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
userLogic "github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
func GetSubscribeStatusHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.GetSubscribeStatusRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
l := userLogic.NewGetSubscribeStatusLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetSubscribeStatus(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get user invite statistics
|
||||
func GetUserInviteStatsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.GetUserInviteStatsRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewGetUserInviteStatsLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetUserInviteStats(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,25 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/public/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Query User Subscribe
|
||||
func QueryUserSubscribeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
// 1. Get param from URL Query (?includeExpired=all)
|
||||
value := c.Query("includeExpired")
|
||||
|
||||
l := user.NewQueryUserSubscribeLogic(c.Request.Context(), svcCtx)
|
||||
// 2. Inject param into Request Context
|
||||
ctx := context.WithValue(c.Request.Context(), constant.CtxKeyIncludeExpired, value)
|
||||
|
||||
l := user.NewQueryUserSubscribeLogic(ctx, svcCtx)
|
||||
resp, err := l.QueryUserSubscribe()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user