refactor(api): remove deprecated application-related endpoints and types
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Create application
|
||||
func CreateApplicationHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.CreateApplicationRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := system.NewCreateApplicationLogic(c.Request.Context(), svcCtx)
|
||||
err := l.CreateApplication(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Create application version
|
||||
func CreateApplicationVersionHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.CreateApplicationVersionRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := system.NewCreateApplicationVersionLogic(c.Request.Context(), svcCtx)
|
||||
err := l.CreateApplicationVersion(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Delete application
|
||||
func DeleteApplicationHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.DeleteApplicationRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := system.NewDeleteApplicationLogic(c.Request.Context(), svcCtx)
|
||||
err := l.DeleteApplication(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Delete application
|
||||
func DeleteApplicationVersionHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.DeleteApplicationVersionRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := system.NewDeleteApplicationVersionLogic(c.Request.Context(), svcCtx)
|
||||
err := l.DeleteApplicationVersion(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// get application config
|
||||
func GetApplicationConfigHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := system.NewGetApplicationConfigLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetApplicationConfig()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get application
|
||||
func GetApplicationHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := system.NewGetApplicationLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetApplication()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// update application config
|
||||
func UpdateApplicationConfigHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.ApplicationConfig
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := system.NewUpdateApplicationConfigLogic(c.Request.Context(), svcCtx)
|
||||
err := l.UpdateApplicationConfig(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Update application
|
||||
func UpdateApplicationHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.UpdateApplicationRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := system.NewUpdateApplicationLogic(c.Request.Context(), svcCtx)
|
||||
err := l.UpdateApplication(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/admin/system"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Update application version
|
||||
func UpdateApplicationVersionHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.UpdateApplicationVersionRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := system.NewUpdateApplicationVersionLogic(c.Request.Context(), svcCtx)
|
||||
err := l.UpdateApplicationVersion(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package announcement
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/announcement"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Query announcement
|
||||
func QueryAnnouncementHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.QueryAnnouncementRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := announcement.NewQueryAnnouncementLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryAnnouncement(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/auth"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Check Account
|
||||
func CheckHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AppAuthCheckRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := auth.NewCheckLogic(c, svcCtx)
|
||||
resp, err := l.Check(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/auth"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// GetAppConfig
|
||||
func GetAppConfigHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AppConfigRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := auth.NewGetAppConfigLogic(c, svcCtx)
|
||||
resp, err := l.GetAppConfig(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/auth"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
"github.com/perfect-panel/server/pkg/turnstile"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Login
|
||||
func LoginHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AppAuthRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
if svcCtx.Config.Verify.LoginVerify {
|
||||
verifyTurns := turnstile.New(turnstile.Config{
|
||||
Secret: svcCtx.Config.Verify.TurnstileSecret,
|
||||
Timeout: 3 * time.Second,
|
||||
})
|
||||
if verify, err := verifyTurns.Verify(c, req.CfToken, c.ClientIP()); err != nil || !verify {
|
||||
err = errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "error: %v, verify: %v", err, verify)
|
||||
result.HttpResult(c, nil, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
l := auth.NewLoginLogic(c, svcCtx)
|
||||
resp, err := l.Login(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/auth"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
"github.com/perfect-panel/server/pkg/turnstile"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Register
|
||||
func RegisterHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AppAuthRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
// get client ip
|
||||
if svcCtx.Config.Verify.RegisterVerify {
|
||||
verifyTurns := turnstile.New(turnstile.Config{
|
||||
Secret: svcCtx.Config.Verify.TurnstileSecret,
|
||||
Timeout: 3 * time.Second,
|
||||
})
|
||||
if verify, err := verifyTurns.Verify(c, req.CfToken, c.ClientIP()); err != nil || !verify {
|
||||
err = errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "error: %v, verify: %v", err, verify)
|
||||
result.HttpResult(c, nil, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
l := auth.NewRegisterLogic(c, svcCtx)
|
||||
resp, err := l.Register(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/auth"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
"github.com/perfect-panel/server/pkg/turnstile"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Reset Password
|
||||
func ResetPasswordHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AppAuthRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
if svcCtx.Config.Verify.ResetPasswordVerify {
|
||||
verifyTurns := turnstile.New(turnstile.Config{
|
||||
Secret: svcCtx.Config.Verify.TurnstileSecret,
|
||||
Timeout: 3 * time.Second,
|
||||
})
|
||||
if verify, err := verifyTurns.Verify(c, req.CfToken, c.ClientIP()); err != nil || !verify {
|
||||
err = errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "error: %v, verify: %v", err, verify)
|
||||
result.HttpResult(c, nil, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
l := auth.NewResetPasswordLogic(c, svcCtx)
|
||||
resp, err := l.ResetPassword(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package document
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/document"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get document detail
|
||||
func QueryDocumentDetailHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.QueryDocumentDetailRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := document.NewQueryDocumentDetailLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryDocumentDetail(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package document
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/document"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get document list
|
||||
func QueryDocumentListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := document.NewQueryDocumentListLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryDocumentList()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/node"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get Node list
|
||||
func GetNodeListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AppUserSubscbribeNodeRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := node.NewGetNodeListLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetNodeList(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/node"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get rule group list
|
||||
func GetRuleGroupListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := node.NewGetRuleGroupListLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetRuleGroupList()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Checkout order
|
||||
func CheckoutOrderHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.CheckoutOrderRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewCheckoutOrderLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.CheckoutOrder(&req, c.Request.Host)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Close order
|
||||
func CloseOrderHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.CloseOrderRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewCloseOrderLogic(c.Request.Context(), svcCtx)
|
||||
err := l.CloseOrder(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Pre create order
|
||||
func PreCreateOrderHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.PurchaseOrderRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewPreCreateOrderLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.PreCreateOrder(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// purchase Subscription
|
||||
func PurchaseHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.PurchaseOrderRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewPurchaseLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.Purchase(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get order
|
||||
func QueryOrderDetailHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.QueryOrderDetailRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewQueryOrderDetailLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryOrderDetail(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get order list
|
||||
func QueryOrderListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.QueryOrderListRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewQueryOrderListLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryOrderList(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Recharge
|
||||
func RechargeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.RechargeOrderRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewRechargeLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.Recharge(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Renewal Subscription
|
||||
func RenewalHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.RenewalOrderRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewRenewalLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.Renewal(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/order"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Reset traffic
|
||||
func ResetTrafficHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.ResetTrafficOrderRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := order.NewResetTrafficLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.ResetTraffic(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/payment"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get available payment methods
|
||||
func GetAvailablePaymentMethodsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := payment.NewGetAvailablePaymentMethodsLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetAvailablePaymentMethods()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/subscribe"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get application config
|
||||
func QueryApplicationConfigHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := subscribe.NewQueryApplicationConfigLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryApplicationConfig()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/subscribe"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get subscribe group list
|
||||
func QuerySubscribeGroupListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := subscribe.NewQuerySubscribeGroupListLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QuerySubscribeGroupList()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/subscribe"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get subscribe list
|
||||
func QuerySubscribeListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := subscribe.NewQuerySubscribeListLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QuerySubscribeList()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/subscribe"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get Already subscribed to package
|
||||
func QueryUserAlreadySubscribeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := subscribe.NewQueryUserAlreadySubscribeLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryUserAlreadySubscribe()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/subscribe"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get Available subscriptions for users
|
||||
func QueryUserAvailableUserSubscribeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.AppUserSubscribeRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := subscribe.NewQueryUserAvailableUserSubscribeLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryUserAvailableUserSubscribe(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/subscribe"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Reset user subscription period
|
||||
func ResetUserSubscribePeriodHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.UserSubscribeResetPeriodRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := subscribe.NewResetUserSubscribePeriodLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.ResetUserSubscribePeriod(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Delete Account
|
||||
func DeleteAccountHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.DeleteAccountRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewDeleteAccountLogic(c.Request.Context(), svcCtx)
|
||||
err := l.DeleteAccount(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get user online time total
|
||||
func GetUserOnlineTimeStatisticsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := user.NewGetUserOnlineTimeStatisticsLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetUserOnlineTimeStatistics()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get user subcribe traffic logs
|
||||
func GetUserSubscribeTrafficLogsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.GetUserSubscribeTrafficLogsRequest
|
||||
_ = c.BindQuery(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewGetUserSubscribeTrafficLogsLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetUserSubscribeTrafficLogs(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// query user info
|
||||
func QueryUserInfoHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := user.NewQueryUserInfoLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryUserInfo()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Query User Affiliate Count
|
||||
func QueryUserAffiliateHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := user.NewQueryUserAffiliateLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryUserAffiliate()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Query User Affiliate List
|
||||
func QueryUserAffiliateListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.QueryUserAffiliateListRequest
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewQueryUserAffiliateListLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryUserAffiliateList(&req)
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Update Password
|
||||
func UpdatePasswordHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
var req types.UpdatePasswordRequeset
|
||||
_ = c.ShouldBind(&req)
|
||||
validateErr := svcCtx.Validate(&req)
|
||||
if validateErr != nil {
|
||||
result.ParamErrorResult(c, validateErr)
|
||||
return
|
||||
}
|
||||
|
||||
l := user.NewUpdatePasswordLogic(c.Request.Context(), svcCtx)
|
||||
err := l.UpdatePassword(&req)
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package ws
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/app/ws"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// App heartbeat
|
||||
func AppWsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
// Logic: App heartbeat
|
||||
l := ws.NewAppWsLogic(ctx, svcCtx)
|
||||
err := l.AppWs(c.Writer, c.Request, c.Param("userid"), c.Param("identifier"))
|
||||
result.HttpResult(c, nil, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get Tos Content
|
||||
func GetApplicationHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := common.NewGetApplicationLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.GetApplication()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/logic/public/subscribe"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
)
|
||||
|
||||
// Get application config
|
||||
func QueryApplicationConfigHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
l := subscribe.NewQueryApplicationConfigLogic(c.Request.Context(), svcCtx)
|
||||
resp, err := l.QueryApplicationConfig()
|
||||
result.HttpResult(c, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,6 @@ import (
|
||||
adminTicket "github.com/perfect-panel/server/internal/handler/admin/ticket"
|
||||
adminTool "github.com/perfect-panel/server/internal/handler/admin/tool"
|
||||
adminUser "github.com/perfect-panel/server/internal/handler/admin/user"
|
||||
appAnnouncement "github.com/perfect-panel/server/internal/handler/app/announcement"
|
||||
appAuth "github.com/perfect-panel/server/internal/handler/app/auth"
|
||||
appDocument "github.com/perfect-panel/server/internal/handler/app/document"
|
||||
appNode "github.com/perfect-panel/server/internal/handler/app/node"
|
||||
appOrder "github.com/perfect-panel/server/internal/handler/app/order"
|
||||
appPayment "github.com/perfect-panel/server/internal/handler/app/payment"
|
||||
appSubscribe "github.com/perfect-panel/server/internal/handler/app/subscribe"
|
||||
appUser "github.com/perfect-panel/server/internal/handler/app/user"
|
||||
appWs "github.com/perfect-panel/server/internal/handler/app/ws"
|
||||
auth "github.com/perfect-panel/server/internal/handler/auth"
|
||||
authOauth "github.com/perfect-panel/server/internal/handler/auth/oauth"
|
||||
common "github.com/perfect-panel/server/internal/handler/common"
|
||||
@@ -357,33 +348,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
|
||||
adminSystemGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Get application
|
||||
adminSystemGroupRouter.GET("/application", adminSystem.GetApplicationHandler(serverCtx))
|
||||
|
||||
// Update application
|
||||
adminSystemGroupRouter.PUT("/application", adminSystem.UpdateApplicationHandler(serverCtx))
|
||||
|
||||
// Create application
|
||||
adminSystemGroupRouter.POST("/application", adminSystem.CreateApplicationHandler(serverCtx))
|
||||
|
||||
// Delete application
|
||||
adminSystemGroupRouter.DELETE("/application", adminSystem.DeleteApplicationHandler(serverCtx))
|
||||
|
||||
// update application config
|
||||
adminSystemGroupRouter.PUT("/application_config", adminSystem.UpdateApplicationConfigHandler(serverCtx))
|
||||
|
||||
// get application config
|
||||
adminSystemGroupRouter.GET("/application_config", adminSystem.GetApplicationConfigHandler(serverCtx))
|
||||
|
||||
// Update application version
|
||||
adminSystemGroupRouter.PUT("/application_version", adminSystem.UpdateApplicationVersionHandler(serverCtx))
|
||||
|
||||
// Create application version
|
||||
adminSystemGroupRouter.POST("/application_version", adminSystem.CreateApplicationVersionHandler(serverCtx))
|
||||
|
||||
// Delete application
|
||||
adminSystemGroupRouter.DELETE("/application_version", adminSystem.DeleteApplicationVersionHandler(serverCtx))
|
||||
|
||||
// Get Currency Config
|
||||
adminSystemGroupRouter.GET("/currency_config", adminSystem.GetCurrencyConfigHandler(serverCtx))
|
||||
|
||||
@@ -565,153 +529,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
|
||||
adminUserGroupRouter.GET("/subscribe/traffic_logs", adminUser.GetUserSubscribeTrafficLogsHandler(serverCtx))
|
||||
}
|
||||
|
||||
appAnnouncementGroupRouter := router.Group("/v1/app/announcement")
|
||||
appAnnouncementGroupRouter.Use(middleware.AppMiddleware(serverCtx), middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Query announcement
|
||||
appAnnouncementGroupRouter.GET("/list", appAnnouncement.QueryAnnouncementHandler(serverCtx))
|
||||
}
|
||||
|
||||
appAuthGroupRouter := router.Group("/v1/app/auth")
|
||||
appAuthGroupRouter.Use(middleware.AppMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Check Account
|
||||
appAuthGroupRouter.POST("/check", appAuth.CheckHandler(serverCtx))
|
||||
|
||||
// GetAppConfig
|
||||
appAuthGroupRouter.POST("/config", appAuth.GetAppConfigHandler(serverCtx))
|
||||
|
||||
// Login
|
||||
appAuthGroupRouter.POST("/login", appAuth.LoginHandler(serverCtx))
|
||||
|
||||
// Register
|
||||
appAuthGroupRouter.POST("/register", appAuth.RegisterHandler(serverCtx))
|
||||
|
||||
// Reset Password
|
||||
appAuthGroupRouter.POST("/reset_password", appAuth.ResetPasswordHandler(serverCtx))
|
||||
}
|
||||
|
||||
appDocumentGroupRouter := router.Group("/v1/app/document")
|
||||
appDocumentGroupRouter.Use(middleware.AppMiddleware(serverCtx), middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Get document detail
|
||||
appDocumentGroupRouter.GET("/detail", appDocument.QueryDocumentDetailHandler(serverCtx))
|
||||
|
||||
// Get document list
|
||||
appDocumentGroupRouter.GET("/list", appDocument.QueryDocumentListHandler(serverCtx))
|
||||
}
|
||||
|
||||
appNodeGroupRouter := router.Group("/v1/app/node")
|
||||
appNodeGroupRouter.Use(middleware.AppMiddleware(serverCtx), middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Get Node list
|
||||
appNodeGroupRouter.GET("/list", appNode.GetNodeListHandler(serverCtx))
|
||||
|
||||
// Get rule group list
|
||||
appNodeGroupRouter.GET("/rule_group_list", appNode.GetRuleGroupListHandler(serverCtx))
|
||||
}
|
||||
|
||||
appOrderGroupRouter := router.Group("/v1/app/order")
|
||||
appOrderGroupRouter.Use(middleware.AppMiddleware(serverCtx), middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Checkout order
|
||||
appOrderGroupRouter.POST("/checkout", appOrder.CheckoutOrderHandler(serverCtx))
|
||||
|
||||
// Close order
|
||||
appOrderGroupRouter.POST("/close", appOrder.CloseOrderHandler(serverCtx))
|
||||
|
||||
// Get order
|
||||
appOrderGroupRouter.GET("/detail", appOrder.QueryOrderDetailHandler(serverCtx))
|
||||
|
||||
// Get order list
|
||||
appOrderGroupRouter.GET("/list", appOrder.QueryOrderListHandler(serverCtx))
|
||||
|
||||
// Pre create order
|
||||
appOrderGroupRouter.POST("/pre", appOrder.PreCreateOrderHandler(serverCtx))
|
||||
|
||||
// purchase Subscription
|
||||
appOrderGroupRouter.POST("/purchase", appOrder.PurchaseHandler(serverCtx))
|
||||
|
||||
// Recharge
|
||||
appOrderGroupRouter.POST("/recharge", appOrder.RechargeHandler(serverCtx))
|
||||
|
||||
// Renewal Subscription
|
||||
appOrderGroupRouter.POST("/renewal", appOrder.RenewalHandler(serverCtx))
|
||||
|
||||
// Reset traffic
|
||||
appOrderGroupRouter.POST("/reset", appOrder.ResetTrafficHandler(serverCtx))
|
||||
}
|
||||
|
||||
appPaymentGroupRouter := router.Group("/v1/app/payment")
|
||||
appPaymentGroupRouter.Use(middleware.AppMiddleware(serverCtx), middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Get available payment methods
|
||||
appPaymentGroupRouter.GET("/methods", appPayment.GetAvailablePaymentMethodsHandler(serverCtx))
|
||||
}
|
||||
|
||||
appSubscribeGroupRouter := router.Group("/v1/app/subscribe")
|
||||
appSubscribeGroupRouter.Use(middleware.AppMiddleware(serverCtx), middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Get application config
|
||||
appSubscribeGroupRouter.GET("/application/config", appSubscribe.QueryApplicationConfigHandler(serverCtx))
|
||||
|
||||
// Get subscribe group list
|
||||
appSubscribeGroupRouter.GET("/group/list", appSubscribe.QuerySubscribeGroupListHandler(serverCtx))
|
||||
|
||||
// Get subscribe list
|
||||
appSubscribeGroupRouter.GET("/list", appSubscribe.QuerySubscribeListHandler(serverCtx))
|
||||
|
||||
// Reset user subscription period
|
||||
appSubscribeGroupRouter.POST("/reset/period", appSubscribe.ResetUserSubscribePeriodHandler(serverCtx))
|
||||
|
||||
// Get Already subscribed to package
|
||||
appSubscribeGroupRouter.GET("/user/already_subscribe", appSubscribe.QueryUserAlreadySubscribeHandler(serverCtx))
|
||||
|
||||
// Get Available subscriptions for users
|
||||
appSubscribeGroupRouter.GET("/user/available_subscribe", appSubscribe.QueryUserAvailableUserSubscribeHandler(serverCtx))
|
||||
}
|
||||
|
||||
appUserGroupRouter := router.Group("/v1/app/user")
|
||||
appUserGroupRouter.Use(middleware.AppMiddleware(serverCtx), middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Delete Account
|
||||
appUserGroupRouter.DELETE("/account", appUser.DeleteAccountHandler(serverCtx))
|
||||
|
||||
// Query User Affiliate Count
|
||||
appUserGroupRouter.GET("/affiliate/count", appUser.QueryUserAffiliateHandler(serverCtx))
|
||||
|
||||
// Query User Affiliate List
|
||||
appUserGroupRouter.GET("/affiliate/list", appUser.QueryUserAffiliateListHandler(serverCtx))
|
||||
|
||||
// query user info
|
||||
appUserGroupRouter.GET("/info", appUser.QueryUserInfoHandler(serverCtx))
|
||||
|
||||
// Get user online time total
|
||||
appUserGroupRouter.GET("/online_time/statistics", appUser.GetUserOnlineTimeStatisticsHandler(serverCtx))
|
||||
|
||||
// Update Password
|
||||
appUserGroupRouter.PUT("/password", appUser.UpdatePasswordHandler(serverCtx))
|
||||
|
||||
// Get user subcribe traffic logs
|
||||
appUserGroupRouter.GET("/subscribe/traffic_logs", appUser.GetUserSubscribeTrafficLogsHandler(serverCtx))
|
||||
}
|
||||
|
||||
appWsGroupRouter := router.Group("/v1/app/ws")
|
||||
appWsGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// App heartbeat
|
||||
appWsGroupRouter.GET("/:userid/:identifier", appWs.AppWsHandler(serverCtx))
|
||||
}
|
||||
|
||||
authGroupRouter := router.Group("/v1/auth")
|
||||
|
||||
{
|
||||
@@ -759,9 +576,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
|
||||
// Get Ads
|
||||
commonGroupRouter.GET("/ads", common.GetAdsHandler(serverCtx))
|
||||
|
||||
// Get Tos Content
|
||||
commonGroupRouter.GET("/application", common.GetApplicationHandler(serverCtx))
|
||||
|
||||
// Check verification code
|
||||
commonGroupRouter.POST("/check_verification_code", common.CheckVerificationCodeHandler(serverCtx))
|
||||
|
||||
@@ -869,9 +683,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
|
||||
publicSubscribeGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
|
||||
|
||||
{
|
||||
// Get application config
|
||||
publicSubscribeGroupRouter.GET("/application/config", publicSubscribe.QueryApplicationConfigHandler(serverCtx))
|
||||
|
||||
// Get subscribe group list
|
||||
publicSubscribeGroupRouter.GET("/group/list", publicSubscribe.QuerySubscribeGroupListHandler(serverCtx))
|
||||
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"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 CreateApplicationLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCreateApplicationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateApplicationLogic {
|
||||
return &CreateApplicationLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateApplicationLogic) CreateApplication(req *types.CreateApplicationRequest) error {
|
||||
var ios []application.ApplicationVersion
|
||||
if len(req.Platform.IOS) > 0 {
|
||||
for _, ios_ := range req.Platform.IOS {
|
||||
ios = append(ios, application.ApplicationVersion{
|
||||
Url: ios_.Url,
|
||||
Version: ios_.Version,
|
||||
Platform: "ios",
|
||||
IsDefault: ios_.IsDefault,
|
||||
Description: ios_.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var mac []application.ApplicationVersion
|
||||
if len(req.Platform.MacOS) > 0 {
|
||||
for _, mac_ := range req.Platform.MacOS {
|
||||
mac = append(mac, application.ApplicationVersion{
|
||||
Url: mac_.Url,
|
||||
Version: mac_.Version,
|
||||
Platform: "macos",
|
||||
IsDefault: mac_.IsDefault,
|
||||
Description: mac_.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var linux []application.ApplicationVersion
|
||||
if len(req.Platform.Linux) > 0 {
|
||||
for _, linux_ := range req.Platform.Linux {
|
||||
linux = append(linux, application.ApplicationVersion{
|
||||
Url: linux_.Url,
|
||||
Version: linux_.Version,
|
||||
Platform: "linux",
|
||||
IsDefault: linux_.IsDefault,
|
||||
Description: linux_.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var android []application.ApplicationVersion
|
||||
if len(req.Platform.Android) > 0 {
|
||||
for _, android_ := range req.Platform.Android {
|
||||
android = append(android, application.ApplicationVersion{
|
||||
Url: android_.Url,
|
||||
Version: android_.Version,
|
||||
Platform: "android",
|
||||
IsDefault: android_.IsDefault,
|
||||
Description: android_.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var windows []application.ApplicationVersion
|
||||
if len(req.Platform.Windows) > 0 {
|
||||
for _, windows_ := range req.Platform.Windows {
|
||||
windows = append(windows, application.ApplicationVersion{
|
||||
Url: windows_.Url,
|
||||
Version: windows_.Version,
|
||||
Platform: "windows",
|
||||
IsDefault: windows_.IsDefault,
|
||||
Description: windows_.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var harmony []application.ApplicationVersion
|
||||
if len(req.Platform.Harmony) > 0 {
|
||||
for _, harmony_ := range req.Platform.Harmony {
|
||||
harmony = append(harmony, application.ApplicationVersion{
|
||||
Url: harmony_.Url,
|
||||
Version: harmony_.Version,
|
||||
Platform: "harmony",
|
||||
IsDefault: harmony_.IsDefault,
|
||||
Description: harmony_.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
var applicationVersions []application.ApplicationVersion
|
||||
applicationVersions = append(applicationVersions, ios...)
|
||||
applicationVersions = append(applicationVersions, mac...)
|
||||
applicationVersions = append(applicationVersions, linux...)
|
||||
applicationVersions = append(applicationVersions, android...)
|
||||
applicationVersions = append(applicationVersions, windows...)
|
||||
applicationVersions = append(applicationVersions, harmony...)
|
||||
app := application.Application{
|
||||
Name: req.Name,
|
||||
Icon: req.Icon,
|
||||
SubscribeType: req.SubscribeType,
|
||||
ApplicationVersions: applicationVersions,
|
||||
}
|
||||
err := l.svcCtx.ApplicationModel.Insert(l.ctx, &app)
|
||||
if err != nil {
|
||||
l.Errorw("[CreateApplicationLogic] create application error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create application error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"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 CreateApplicationVersionLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Create application version
|
||||
func NewCreateApplicationVersionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateApplicationVersionLogic {
|
||||
return &CreateApplicationVersionLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateApplicationVersionLogic) CreateApplicationVersion(req *types.CreateApplicationVersionRequest) error {
|
||||
create := &application.ApplicationVersion{
|
||||
Url: req.Url,
|
||||
Platform: req.Platform,
|
||||
Version: req.Version,
|
||||
Description: req.Description,
|
||||
IsDefault: req.IsDefault,
|
||||
ApplicationId: req.ApplicationId,
|
||||
}
|
||||
err := l.svcCtx.ApplicationModel.InsertVersion(l.ctx, create)
|
||||
if err != nil {
|
||||
l.Errorw("[CreateApplicationVersion] create application version error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create application version error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package system
|
||||
|
||||
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 DeleteApplicationLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewDeleteApplicationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteApplicationLogic {
|
||||
return &DeleteApplicationLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *DeleteApplicationLogic) DeleteApplication(req *types.DeleteApplicationRequest) error {
|
||||
// delete application
|
||||
err := l.svcCtx.ApplicationModel.Delete(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
l.Errorw("[DeleteApplicationLogic] delete application error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "delete application error: %v", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package system
|
||||
|
||||
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 DeleteApplicationVersionLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Delete application
|
||||
func NewDeleteApplicationVersionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteApplicationVersionLogic {
|
||||
return &DeleteApplicationVersionLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *DeleteApplicationVersionLogic) DeleteApplicationVersion(req *types.DeleteApplicationVersionRequest) error {
|
||||
// delete application
|
||||
err := l.svcCtx.ApplicationModel.DeleteVersion(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
l.Errorw("[DeleteApplicationVersion] delete application version error: ", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "delete application version error: %v", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type GetApplicationConfigLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// get application config
|
||||
func NewGetApplicationConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetApplicationConfigLogic {
|
||||
return &GetApplicationConfigLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetApplicationConfigLogic) GetApplicationConfig() (resp *types.ApplicationConfig, err error) {
|
||||
resp = &types.ApplicationConfig{}
|
||||
appConfig, err := l.svcCtx.ApplicationModel.FindOneConfig(l.ctx, 1)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
l.Errorw("[GetApplicationConfig] Database Error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get app config error: %v", err.Error())
|
||||
}
|
||||
resp.AppId = appConfig.AppId
|
||||
resp.EncryptionKey = appConfig.EncryptionKey
|
||||
resp.EncryptionMethod = appConfig.EncryptionMethod
|
||||
resp.Domains = strings.Split(appConfig.Domains, ";")
|
||||
resp.StartupPicture = appConfig.StartupPicture
|
||||
resp.StartupPictureSkipTime = appConfig.StartupPictureSkipTime
|
||||
return
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type GetApplicationLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get application
|
||||
func NewGetApplicationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetApplicationLogic {
|
||||
return &GetApplicationLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetApplicationLogic) GetApplication() (resp *types.ApplicationResponse, err error) {
|
||||
resp = &types.ApplicationResponse{}
|
||||
var applications []*application.Application
|
||||
err = l.svcCtx.ApplicationModel.Transaction(l.ctx, func(tx *gorm.DB) (err error) {
|
||||
return tx.Model(applications).Preload("ApplicationVersions").Find(&applications).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[GetApplicationLogic] get application error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get application error: %v", err.Error())
|
||||
}
|
||||
|
||||
if len(applications) == 0 {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
for _, app := range applications {
|
||||
applicationResponse := types.ApplicationResponseInfo{
|
||||
Id: app.Id,
|
||||
Name: app.Name,
|
||||
Icon: app.Icon,
|
||||
Description: app.Description,
|
||||
SubscribeType: app.SubscribeType,
|
||||
}
|
||||
applicationVersions := app.ApplicationVersions
|
||||
if len(applicationVersions) != 0 {
|
||||
for _, applicationVersion := range applicationVersions {
|
||||
switch applicationVersion.Platform {
|
||||
case "ios":
|
||||
applicationResponse.Platform.IOS = append(applicationResponse.Platform.IOS, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "macos":
|
||||
applicationResponse.Platform.MacOS = append(applicationResponse.Platform.MacOS, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "linux":
|
||||
applicationResponse.Platform.Linux = append(applicationResponse.Platform.Linux, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "android":
|
||||
applicationResponse.Platform.Android = append(applicationResponse.Platform.Android, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "windows":
|
||||
applicationResponse.Platform.Windows = append(applicationResponse.Platform.Windows, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "harmony":
|
||||
applicationResponse.Platform.Harmony = append(applicationResponse.Platform.Harmony, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
resp.Applications = append(resp.Applications, applicationResponse)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"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 UpdateApplicationConfigLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// update application config
|
||||
func NewUpdateApplicationConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateApplicationConfigLogic {
|
||||
return &UpdateApplicationConfigLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UpdateApplicationConfigLogic) UpdateApplicationConfig(req *types.ApplicationConfig) error {
|
||||
err := l.svcCtx.ApplicationModel.UpdateConfig(l.ctx, &application.ApplicationConfig{
|
||||
Id: 1,
|
||||
AppId: req.AppId,
|
||||
EncryptionKey: req.EncryptionKey,
|
||||
EncryptionMethod: req.EncryptionMethod,
|
||||
Domains: strings.Join(req.Domains, ";"),
|
||||
StartupPicture: req.StartupPicture,
|
||||
StartupPictureSkipTime: req.StartupPictureSkipTime,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateApplicationConfig] Database Error", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update app config error: %v", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
)
|
||||
|
||||
type UpdateApplicationLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewUpdateApplicationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateApplicationLogic {
|
||||
return &UpdateApplicationLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UpdateApplicationLogic) UpdateApplication(req *types.UpdateApplicationRequest) error {
|
||||
|
||||
// find application
|
||||
app, err := l.svcCtx.ApplicationModel.FindOne(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateApplication] find application error", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find application error: %v", err.Error())
|
||||
}
|
||||
app.Name = req.Name
|
||||
app.Icon = req.Icon
|
||||
app.SubscribeType = req.SubscribeType
|
||||
app.Description = req.Description
|
||||
|
||||
var ios []application.ApplicationVersion
|
||||
if len(req.Platform.IOS) > 0 {
|
||||
for _, ios_ := range req.Platform.IOS {
|
||||
ios = append(ios, application.ApplicationVersion{
|
||||
Url: ios_.Url,
|
||||
Version: ios_.Version,
|
||||
Platform: "ios",
|
||||
IsDefault: ios_.IsDefault,
|
||||
Description: ios_.Description,
|
||||
ApplicationId: app.Id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var mac []application.ApplicationVersion
|
||||
if len(req.Platform.MacOS) > 0 {
|
||||
for _, mac_ := range req.Platform.MacOS {
|
||||
mac = append(mac, application.ApplicationVersion{
|
||||
Url: mac_.Url,
|
||||
Version: mac_.Version,
|
||||
Platform: "macos",
|
||||
IsDefault: mac_.IsDefault,
|
||||
Description: mac_.Description,
|
||||
ApplicationId: app.Id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var linux []application.ApplicationVersion
|
||||
if len(req.Platform.Linux) > 0 {
|
||||
for _, linux_ := range req.Platform.Linux {
|
||||
linux = append(linux, application.ApplicationVersion{
|
||||
Url: linux_.Url,
|
||||
Version: linux_.Version,
|
||||
Platform: "linux",
|
||||
IsDefault: linux_.IsDefault,
|
||||
Description: linux_.Description,
|
||||
ApplicationId: app.Id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var android []application.ApplicationVersion
|
||||
if len(req.Platform.Android) > 0 {
|
||||
for _, android_ := range req.Platform.Android {
|
||||
android = append(android, application.ApplicationVersion{
|
||||
Url: android_.Url,
|
||||
Version: android_.Version,
|
||||
Platform: "android",
|
||||
IsDefault: android_.IsDefault,
|
||||
Description: android_.Description,
|
||||
ApplicationId: app.Id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var windows []application.ApplicationVersion
|
||||
if len(req.Platform.Windows) > 0 {
|
||||
for _, windows_ := range req.Platform.Windows {
|
||||
windows = append(windows, application.ApplicationVersion{
|
||||
Url: windows_.Url,
|
||||
Version: windows_.Version,
|
||||
Platform: "windows",
|
||||
IsDefault: windows_.IsDefault,
|
||||
Description: windows_.Description,
|
||||
ApplicationId: app.Id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var harmony []application.ApplicationVersion
|
||||
if len(req.Platform.Harmony) > 0 {
|
||||
for _, harmony_ := range req.Platform.Harmony {
|
||||
harmony = append(harmony, application.ApplicationVersion{
|
||||
Url: harmony_.Url,
|
||||
Version: harmony_.Version,
|
||||
Platform: "harmony",
|
||||
IsDefault: harmony_.IsDefault,
|
||||
Description: harmony_.Description,
|
||||
ApplicationId: app.Id,
|
||||
})
|
||||
}
|
||||
}
|
||||
var applicationVersions []application.ApplicationVersion
|
||||
applicationVersions = append(applicationVersions, ios...)
|
||||
applicationVersions = append(applicationVersions, mac...)
|
||||
applicationVersions = append(applicationVersions, linux...)
|
||||
applicationVersions = append(applicationVersions, android...)
|
||||
applicationVersions = append(applicationVersions, windows...)
|
||||
applicationVersions = append(applicationVersions, harmony...)
|
||||
app.ApplicationVersions = applicationVersions
|
||||
err = l.svcCtx.ApplicationModel.Transaction(l.ctx, func(db *gorm.DB) error {
|
||||
|
||||
if err = db.Where("application_id = ?", app.Id).Delete(&application.ApplicationVersion{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err = db.Create(&applicationVersions).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return db.Save(app).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateApplication] update application error", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update application error: %v", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package system
|
||||
|
||||
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 UpdateApplicationVersionLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Update application version
|
||||
func NewUpdateApplicationVersionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateApplicationVersionLogic {
|
||||
return &UpdateApplicationVersionLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UpdateApplicationVersionLogic) UpdateApplicationVersion(req *types.UpdateApplicationVersionRequest) error {
|
||||
// find application
|
||||
app, err := l.svcCtx.ApplicationModel.FindOneVersion(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateApplicationVersion] find application version error", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find application error: %v", err.Error())
|
||||
}
|
||||
app.Url = req.Url
|
||||
app.Version = req.Version
|
||||
app.Description = req.Description
|
||||
app.IsDefault = req.IsDefault
|
||||
err = l.svcCtx.ApplicationModel.UpdateVersion(l.ctx, app)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateApplicationVersion] update application version error", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update application version error: %v", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package announcement
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/announcement"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type QueryAnnouncementLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewQueryAnnouncementLogic Query announcement
|
||||
func NewQueryAnnouncementLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryAnnouncementLogic {
|
||||
return &QueryAnnouncementLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryAnnouncementLogic) QueryAnnouncement(req *types.QueryAnnouncementRequest) (resp *types.QueryAnnouncementResponse, err error) {
|
||||
enable := true
|
||||
total, list, err := l.svcCtx.AnnouncementModel.GetAnnouncementListByPage(l.ctx, req.Page, req.Size, announcement.Filter{
|
||||
Show: &enable,
|
||||
Pinned: req.Pinned,
|
||||
Popup: req.Popup,
|
||||
})
|
||||
if err != nil {
|
||||
l.Error("[QueryAnnouncementLogic] GetAnnouncementListByPage error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "GetAnnouncementListByPage error: %v", err.Error())
|
||||
}
|
||||
resp = &types.QueryAnnouncementResponse{}
|
||||
resp.Total = total
|
||||
resp.List = make([]types.Announcement, 0)
|
||||
tool.DeepCopy(&resp.List, list)
|
||||
return
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type CheckLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Check Account
|
||||
func NewCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckLogic {
|
||||
return &CheckLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CheckLogic) Check(req *types.AppAuthCheckRequest) (resp *types.AppAuthCheckResponse, err error) {
|
||||
resp = &types.AppAuthCheckResponse{}
|
||||
_, err = findUserByMethod(l.ctx, l.svcCtx, req.Method, req.Identifier, req.Account, req.AreaCode)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
resp.Status = false
|
||||
return resp, nil
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
resp.Status = true
|
||||
return
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/authmethod"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/phone"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func findUserByMethod(ctx context.Context, svcCtx *svc.ServiceContext, method, identifier, account, areaCode string) (userInfo *user.User, err error) {
|
||||
var authMethods *user.AuthMethods
|
||||
switch method {
|
||||
case authmethod.Email:
|
||||
authMethods, err = svcCtx.UserModel.FindUserAuthMethodByOpenID(ctx, authmethod.Email, account)
|
||||
case authmethod.Mobile:
|
||||
phoneNumber, err := phone.FormatToE164(areaCode, account)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.TelephoneError), "Invalid phone number")
|
||||
}
|
||||
authMethods, err = svcCtx.UserModel.FindUserAuthMethodByOpenID(ctx, authmethod.Mobile, phoneNumber)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case authmethod.Device:
|
||||
userDevice, err := svcCtx.UserModel.FindOneDeviceByIdentifier(ctx, identifier)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query user device imei error")
|
||||
}
|
||||
return svcCtx.UserModel.FindOne(ctx, userDevice.UserId)
|
||||
default:
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserNotExist), "unknown method")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return svcCtx.UserModel.FindOne(ctx, authMethods.UserId)
|
||||
}
|
||||
|
||||
func existError(method string) error {
|
||||
switch method {
|
||||
case authmethod.Email:
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.EmailExist), "")
|
||||
case authmethod.Mobile:
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.TelephoneExist), "")
|
||||
case authmethod.Device:
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DeviceExist), "")
|
||||
default:
|
||||
return errors.New("unknown method")
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type GetAppConfigLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// GetAppConfig
|
||||
func NewGetAppConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAppConfigLogic {
|
||||
return &GetAppConfigLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetAppConfigLogic) GetAppConfig(req *types.AppConfigRequest) (resp *types.AppConfigResponse, err error) {
|
||||
resp = &types.AppConfigResponse{}
|
||||
systems, err := l.svcCtx.SystemModel.GetSiteConfig(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryApplicationConfig] GetSiteConfig error: ", logger.Field("error", err.Error()))
|
||||
}
|
||||
for _, sysVal := range systems {
|
||||
if sysVal.Key == "CustomData" {
|
||||
jsonStr := strings.ReplaceAll(sysVal.Value, "\\", "")
|
||||
customData := make(map[string]interface{})
|
||||
if err = json.Unmarshal([]byte(jsonStr), &customData); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
website := customData["website"]
|
||||
if website != nil {
|
||||
resp.OfficialWebsite = fmt.Sprintf("%v", website)
|
||||
}
|
||||
|
||||
contacts := customData["contacts"]
|
||||
if contacts != nil {
|
||||
contactsJson, err := json.Marshal(contacts)
|
||||
if err == nil {
|
||||
contactsMap := make(map[string]string)
|
||||
err = json.Unmarshal(contactsJson, &contactsMap)
|
||||
if err == nil {
|
||||
resp.OfficialEmail = fmt.Sprintf("%v", contactsMap["email"])
|
||||
resp.OfficialTelegram = fmt.Sprintf("%v", contactsMap["telegram"])
|
||||
resp.OfficialTelephone = fmt.Sprintf("%v", contactsMap["telephone"])
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var applications []*application.Application
|
||||
err = l.svcCtx.ApplicationModel.Transaction(l.ctx, func(tx *gorm.DB) (err error) {
|
||||
return tx.Model(applications).Preload("ApplicationVersions").Find(&applications).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[QueryApplicationConfig] get application error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get application error: %v", err.Error())
|
||||
}
|
||||
|
||||
if len(applications) == 0 {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
isOk := false
|
||||
for _, app := range applications {
|
||||
if isOk {
|
||||
break
|
||||
}
|
||||
resp.Application.Name = app.Name
|
||||
resp.Application.Description = app.Description
|
||||
applicationVersions := app.ApplicationVersions
|
||||
if len(applicationVersions) != 0 {
|
||||
for _, applicationVersion := range applicationVersions {
|
||||
if applicationVersion.Platform == req.UserAgent {
|
||||
resp.Application.Id = applicationVersion.ApplicationId
|
||||
resp.Application.Url = applicationVersion.Url
|
||||
resp.Application.Version = applicationVersion.Version
|
||||
resp.Application.VersionDescription = applicationVersion.Description
|
||||
resp.Application.IsDefault = applicationVersion.IsDefault
|
||||
isOk = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configs, err := l.svcCtx.ApplicationModel.FindOneConfig(l.ctx, 1)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
l.Logger.Error("[GetAppInfo] FindOneAppConfig error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "GetAppInfo FindOneAppConfig error: %v", err.Error())
|
||||
}
|
||||
resp.EncryptionKey = configs.EncryptionKey
|
||||
resp.EncryptionMethod = configs.EncryptionMethod
|
||||
resp.Domains = strings.Split(configs.Domains, ";")
|
||||
resp.StartupPicture = configs.StartupPicture
|
||||
resp.StartupPictureSkipTime = configs.StartupPictureSkipTime
|
||||
resp.InvitationLink = configs.InvitationLink
|
||||
resp.KrWebsiteId = configs.KrWebsiteId
|
||||
return
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/authmethod"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/phone"
|
||||
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/jwt"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/uuidx"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type LoginLogic struct {
|
||||
logger.Logger
|
||||
ctx *gin.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Login
|
||||
func NewLoginLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *LoginLogic {
|
||||
return &LoginLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *LoginLogic) Login(req *types.AppAuthRequest) (resp *types.AppAuthRespone, err error) {
|
||||
|
||||
loginStatus := false
|
||||
var userInfo *user.User
|
||||
// Record login status
|
||||
defer func(svcCtx *svc.ServiceContext) {
|
||||
if userInfo != nil && userInfo.Id != 0 {
|
||||
if err := svcCtx.UserModel.InsertLoginLog(l.ctx, &user.LoginLog{
|
||||
UserId: userInfo.Id,
|
||||
LoginIP: l.ctx.ClientIP(),
|
||||
UserAgent: l.ctx.Request.UserAgent(),
|
||||
Success: &loginStatus,
|
||||
}); err != nil {
|
||||
l.Errorw("InsertLoginLog Error", logger.Field("error", err.Error()))
|
||||
}
|
||||
}
|
||||
}(l.svcCtx)
|
||||
|
||||
resp = &types.AppAuthRespone{}
|
||||
//query user
|
||||
userInfo, err = findUserByMethod(l.ctx, l.svcCtx, req.Method, req.Identifier, req.Account, req.AreaCode)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserPasswordError), "user password")
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
switch req.Method {
|
||||
case authmethod.Email:
|
||||
|
||||
if !l.svcCtx.Config.Email.Enable {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.EmailNotEnabled), "Email function is not enabled yet")
|
||||
}
|
||||
|
||||
if req.Code != "" {
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeCacheKey, constant.Security.String(), req.Account)
|
||||
value, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
l.Errorw("Redis Error", logger.Field("error", err.Error()), logger.Field("cacheKey", cacheKey))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
var payload common.CacheKeyPayload
|
||||
err = json.Unmarshal([]byte(value), &payload)
|
||||
if err != nil {
|
||||
l.Errorw("Unmarshal Error", logger.Field("error", err.Error()), logger.Field("value", value))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
if payload.Code != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
l.svcCtx.Redis.Del(l.ctx, cacheKey)
|
||||
} else {
|
||||
// Verify password
|
||||
if !tool.VerifyPassWord(req.Password, userInfo.Password) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserPasswordError), "user password")
|
||||
}
|
||||
}
|
||||
case authmethod.Mobile:
|
||||
if !l.svcCtx.Config.Mobile.Enable {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SmsNotEnabled), "sms login is not enabled")
|
||||
}
|
||||
phoneNumber, err := phone.FormatToE164(req.AreaCode, req.Account)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.TelephoneError), "Invalid phone number")
|
||||
}
|
||||
|
||||
if req.Code != "" {
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeTelephoneCacheKey, constant.Security, phoneNumber)
|
||||
value, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
l.Errorw("Redis Error", logger.Field("error", err.Error()), logger.Field("cacheKey", cacheKey))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
if value == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
var payload common.CacheKeyPayload
|
||||
if err := json.Unmarshal([]byte(value), &payload); err != nil {
|
||||
l.Errorw("[SendSmsCode]: Unmarshal Error", logger.Field("error", err.Error()), logger.Field("value", value))
|
||||
}
|
||||
if payload.Code != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
l.svcCtx.Redis.Del(l.ctx, cacheKey)
|
||||
} else {
|
||||
// Verify password
|
||||
if !tool.VerifyPassWord(req.Password, userInfo.Password) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserPasswordError), "user password")
|
||||
}
|
||||
}
|
||||
case authmethod.Device:
|
||||
default:
|
||||
return nil, existError(req.Method)
|
||||
}
|
||||
|
||||
device, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, req.Identifier)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
if req.Method == authmethod.Device {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserNotExist), "device not exist")
|
||||
}
|
||||
//Add User Device
|
||||
userInfo.UserDevices = append(userInfo.UserDevices, user.Device{
|
||||
UserAgent: req.UserAgent,
|
||||
Identifier: req.Identifier,
|
||||
Ip: l.ctx.ClientIP(),
|
||||
})
|
||||
err = l.svcCtx.UserModel.Update(l.ctx, userInfo)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateUserBindDevice] Fail", logger.Field("error", err.Error()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Change the user who owns the device
|
||||
if device.UserId != userInfo.Id {
|
||||
device.UserId = userInfo.Id
|
||||
}
|
||||
device.Ip = l.ctx.ClientIP()
|
||||
err = l.svcCtx.UserModel.UpdateDevice(l.ctx, device)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateUserBindDevice] Fail", logger.Field("error", err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
// Generate session id
|
||||
sessionId := uuidx.NewUUID().String()
|
||||
// Generate token
|
||||
token, err := jwt.NewJwtToken(
|
||||
l.svcCtx.Config.JwtAuth.AccessSecret,
|
||||
time.Now().Unix(),
|
||||
l.svcCtx.Config.JwtAuth.AccessExpire,
|
||||
jwt.WithOption("UserId", userInfo.Id),
|
||||
jwt.WithOption("SessionId", sessionId),
|
||||
)
|
||||
if err != nil {
|
||||
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "token generate error: %v", err.Error())
|
||||
}
|
||||
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, sessionIdCacheKey, userInfo.Id, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set session id error: %v", err.Error())
|
||||
}
|
||||
|
||||
resp.Token = token
|
||||
return
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/authmethod"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/jwt"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/phone"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/uuidx"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CacheKeyPayload struct {
|
||||
Code string `json:"code"`
|
||||
LastAt int64 `json:"lastAt"`
|
||||
}
|
||||
type RegisterLogic struct {
|
||||
logger.Logger
|
||||
ctx *gin.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Register
|
||||
func NewRegisterLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *RegisterLogic {
|
||||
return &RegisterLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *RegisterLogic) Register(req *types.AppAuthRequest) (resp *types.AppAuthRespone, err error) {
|
||||
resp = &types.AppAuthRespone{}
|
||||
var referer *user.User
|
||||
c := l.svcCtx.Config.Register
|
||||
// Check if the registration is stopped
|
||||
if c.StopRegister {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.StopRegister), "stop register")
|
||||
}
|
||||
|
||||
if req.Invite == "" {
|
||||
if l.svcCtx.Config.Invite.ForcedInvite {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InviteCodeError), "invite code is required")
|
||||
}
|
||||
} else {
|
||||
// Check if the invite code is valid
|
||||
referer, err = l.svcCtx.UserModel.FindOneByReferCode(l.ctx, req.Invite)
|
||||
if err != nil {
|
||||
l.Errorw("FindOneByReferCode Error", logger.Field("error", err))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InviteCodeError), "invite code is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
if req.Password == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.PasswordIsEmpty), "Password required")
|
||||
}
|
||||
|
||||
userInfo, err := findUserByMethod(l.ctx, l.svcCtx, req.Method, req.Identifier, req.Account, req.AreaCode)
|
||||
if err == nil && userInfo != nil {
|
||||
return nil, existError(req.Method)
|
||||
}
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
// Generate password
|
||||
pwd := tool.EncodePassWord(req.Password)
|
||||
userInfo = &user.User{
|
||||
Password: pwd,
|
||||
}
|
||||
if referer != nil {
|
||||
userInfo.RefererId = referer.Id
|
||||
}
|
||||
switch req.Method {
|
||||
case authmethod.Email:
|
||||
if !l.svcCtx.Config.Email.Enable {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.EmailNotEnabled), "Email function is not enabled yet")
|
||||
}
|
||||
if l.svcCtx.Config.Email.EnableVerify {
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeCacheKey, constant.Register.String(), req.Account)
|
||||
value, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
l.Errorw("Redis Error", logger.Field("error", err.Error()), logger.Field("cacheKey", cacheKey))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
var payload common.CacheKeyPayload
|
||||
err = json.Unmarshal([]byte(value), &payload)
|
||||
if err != nil {
|
||||
l.Errorw("Unmarshal Error", logger.Field("error", err.Error()), logger.Field("value", value))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
if payload.Code != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
}
|
||||
userInfo.AuthMethods = []user.AuthMethods{{
|
||||
AuthType: authmethod.Email,
|
||||
AuthIdentifier: req.Account,
|
||||
}}
|
||||
|
||||
case authmethod.Mobile:
|
||||
if req.AreaCode == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.TelephoneAreaCodeIsEmpty), "area code required")
|
||||
}
|
||||
|
||||
if !l.svcCtx.Config.Mobile.Enable {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SmsNotEnabled), "sms login is not enabled")
|
||||
}
|
||||
phoneNumber, err := phone.FormatToE164(req.AreaCode, req.Account)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.TelephoneError), "Invalid phone number")
|
||||
}
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeTelephoneCacheKey, constant.Register, phoneNumber)
|
||||
value, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
l.Errorw("Redis Error", logger.Field("error", err.Error()), logger.Field("cacheKey", cacheKey))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
var payload CacheKeyPayload
|
||||
_ = json.Unmarshal([]byte(value), &payload)
|
||||
if payload.Code != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
userInfo.AuthMethods = []user.AuthMethods{{
|
||||
AuthType: authmethod.Mobile,
|
||||
AuthIdentifier: phoneNumber,
|
||||
Verified: true,
|
||||
}}
|
||||
case authmethod.Device:
|
||||
oneDevice, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, req.Identifier)
|
||||
if err == nil && oneDevice != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DeviceExist), "device exist")
|
||||
}
|
||||
default:
|
||||
return nil, existError(req.Method)
|
||||
}
|
||||
|
||||
device, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, req.Identifier)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
//Add User Device
|
||||
userInfo.UserDevices = append(userInfo.UserDevices, user.Device{
|
||||
Ip: l.ctx.ClientIP(),
|
||||
Identifier: req.Identifier,
|
||||
UserAgent: req.UserAgent,
|
||||
})
|
||||
} else {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query user info failed: %v", err.Error())
|
||||
}
|
||||
} else {
|
||||
//Delete Other User Device
|
||||
err = l.svcCtx.UserModel.DeleteDevice(l.ctx, device.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "delete old user device failed: %v", err.Error())
|
||||
} else {
|
||||
//User Add Device
|
||||
userInfo.UserDevices = append(userInfo.UserDevices, user.Device{
|
||||
Ip: l.ctx.ClientIP(),
|
||||
Identifier: req.Identifier,
|
||||
UserAgent: req.UserAgent,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
err = l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
|
||||
// Save user information
|
||||
if err := db.Create(userInfo).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// Generate ReferCode
|
||||
userInfo.ReferCode = uuidx.UserInviteCode(userInfo.Id)
|
||||
// Update ReferCode
|
||||
if err := db.Model(&user.User{}).Where("id = ?", userInfo.Id).Update("refer_code", userInfo.ReferCode).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if l.svcCtx.Config.Register.EnableTrial {
|
||||
// Active trial
|
||||
if err = l.activeTrial(userInfo.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "insert user info failed: %v", err.Error())
|
||||
}
|
||||
|
||||
// Generate session id
|
||||
sessionId := uuidx.NewUUID().String()
|
||||
// Generate token
|
||||
token, err := jwt.NewJwtToken(
|
||||
l.svcCtx.Config.JwtAuth.AccessSecret,
|
||||
time.Now().Unix(),
|
||||
l.svcCtx.Config.JwtAuth.AccessExpire,
|
||||
jwt.WithOption("UserId", userInfo.Id),
|
||||
jwt.WithOption("SessionId", sessionId),
|
||||
)
|
||||
if err != nil {
|
||||
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "token generate error: %v", err.Error())
|
||||
}
|
||||
|
||||
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
|
||||
if err := l.svcCtx.Redis.Set(l.ctx, sessionIdCacheKey, userInfo.Id, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set session id error: %v", err.Error())
|
||||
}
|
||||
|
||||
resp.Token = token
|
||||
return
|
||||
}
|
||||
|
||||
func (l *RegisterLogic) activeTrial(uid int64) error {
|
||||
sub, err := l.svcCtx.SubscribeModel.FindOne(l.ctx, l.svcCtx.Config.Register.TrialSubscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userSub := &user.Subscribe{
|
||||
Id: 0,
|
||||
UserId: uid,
|
||||
OrderId: 0,
|
||||
SubscribeId: sub.Id,
|
||||
StartTime: time.Now(),
|
||||
ExpireTime: tool.AddTime(l.svcCtx.Config.Register.TrialTimeUnit, l.svcCtx.Config.Register.TrialTime, time.Now()),
|
||||
Traffic: sub.Traffic,
|
||||
Download: 0,
|
||||
Upload: 0,
|
||||
Token: uuidx.SubscribeToken(fmt.Sprintf("Trial-%v", uid)),
|
||||
UUID: uuidx.NewUUID().String(),
|
||||
Status: 1,
|
||||
}
|
||||
return l.svcCtx.UserModel.InsertSubscribe(l.ctx, userSub)
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/authmethod"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/phone"
|
||||
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/jwt"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/uuidx"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ResetPasswordLogic struct {
|
||||
logger.Logger
|
||||
ctx *gin.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Reset Password
|
||||
func NewResetPasswordLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *ResetPasswordLogic {
|
||||
return &ResetPasswordLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ResetPasswordLogic) ResetPassword(req *types.AppAuthRequest) (resp *types.AppAuthRespone, err error) {
|
||||
resp = &types.AppAuthRespone{}
|
||||
userInfo, err := findUserByMethod(l.ctx, l.svcCtx, req.Method, req.Identifier, req.Account, req.AreaCode)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserNotExist), "query user info failed")
|
||||
}
|
||||
l.Errorw("FindOneByEmail Error", logger.Field("error", err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch req.Method {
|
||||
case authmethod.Mobile:
|
||||
if !l.svcCtx.Config.Mobile.Enable {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SmsNotEnabled), "sms login is not enabled")
|
||||
}
|
||||
phoneNumber, err := phone.FormatToE164(req.AreaCode, req.Account)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.TelephoneError), "Invalid phone number")
|
||||
}
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeTelephoneCacheKey, constant.Security, phoneNumber)
|
||||
value, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
l.Errorw("Redis Error", logger.Field("error", err.Error()), logger.Field("cacheKey", cacheKey))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
var payload common.CacheKeyPayload
|
||||
err = json.Unmarshal([]byte(value), &payload)
|
||||
if err != nil {
|
||||
l.Errorw("Unmarshal Error", logger.Field("error", err.Error()), logger.Field("value", value))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
if payload.Code != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
case authmethod.Email:
|
||||
if !l.svcCtx.Config.Email.Enable {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.EmailNotEnabled), "Email function is not enabled yet")
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeCacheKey, constant.Security.String(), req.Account)
|
||||
value, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
l.Errorw("Redis Error", logger.Field("error", err.Error()), logger.Field("cacheKey", cacheKey))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
var payload CacheKeyPayload
|
||||
err = json.Unmarshal([]byte(value), &payload)
|
||||
if err != nil {
|
||||
l.Errorw("Unmarshal Error", logger.Field("error", err.Error()), logger.Field("value", value))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
if payload.Code != req.Code {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("unknown method")
|
||||
}
|
||||
|
||||
userInfo.Password = tool.EncodePassWord(req.Password)
|
||||
err = l.svcCtx.UserModel.Update(l.ctx, userInfo)
|
||||
if err != nil {
|
||||
l.Errorw("UpdateUser Error", logger.Field("error", err))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update user info failed: %v", err.Error())
|
||||
}
|
||||
|
||||
device, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, req.Identifier)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
//Add User Device
|
||||
userInfo.UserDevices = append(userInfo.UserDevices, user.Device{
|
||||
Ip: l.ctx.ClientIP(),
|
||||
Identifier: req.Identifier,
|
||||
UserAgent: req.UserAgent,
|
||||
})
|
||||
} else {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query user info failed: %v", err.Error())
|
||||
}
|
||||
} else {
|
||||
if device.UserId != userInfo.Id {
|
||||
//Change the user who owns the device
|
||||
if device.UserId != userInfo.Id {
|
||||
device.UserId = userInfo.Id
|
||||
}
|
||||
device.Ip = l.ctx.ClientIP()
|
||||
err = l.svcCtx.UserModel.UpdateDevice(l.ctx, device)
|
||||
if err != nil {
|
||||
l.Errorw("[UpdateUserBindDevice] Fail", logger.Field("error", err.Error()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate session id
|
||||
sessionId := uuidx.NewUUID().String()
|
||||
// Generate token
|
||||
token, err := jwt.NewJwtToken(
|
||||
l.svcCtx.Config.JwtAuth.AccessSecret,
|
||||
time.Now().Unix(),
|
||||
l.svcCtx.Config.JwtAuth.AccessExpire,
|
||||
jwt.WithOption("UserId", userInfo.Id),
|
||||
jwt.WithOption("SessionId", sessionId),
|
||||
)
|
||||
if err != nil {
|
||||
l.Logger.Error("[UserLogin] token generate error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "token generate error: %v", err.Error())
|
||||
}
|
||||
|
||||
sessionIdCacheKey := fmt.Sprintf("%v:%v", config.SessionIdKey, sessionId)
|
||||
if err := l.svcCtx.Redis.Set(l.ctx, sessionIdCacheKey, userInfo.Id, time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire)*time.Second).Err(); err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "set session id error: %v", err.Error())
|
||||
}
|
||||
resp.Token = token
|
||||
return
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package document
|
||||
|
||||
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/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type QueryDocumentDetailLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewQueryDocumentDetailLogic Get document detail
|
||||
func NewQueryDocumentDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryDocumentDetailLogic {
|
||||
return &QueryDocumentDetailLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryDocumentDetailLogic) QueryDocumentDetail(req *types.QueryDocumentDetailRequest) (resp *types.Document, err error) {
|
||||
// find document
|
||||
data, err := l.svcCtx.DocumentModel.FindOne(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
l.Error("[QueryDocumentDetailLogic] FindOne error", logger.Field("id", req.Id), logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "FindOne error: %s", err.Error())
|
||||
}
|
||||
resp = &types.Document{}
|
||||
tool.DeepCopy(resp, data)
|
||||
return
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package document
|
||||
|
||||
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/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type QueryDocumentListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get document list
|
||||
func NewQueryDocumentListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryDocumentListLogic {
|
||||
return &QueryDocumentListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryDocumentListLogic) QueryDocumentList() (resp *types.QueryDocumentListResponse, err error) {
|
||||
total, data, err := l.svcCtx.DocumentModel.GetDocumentListByAll(l.ctx)
|
||||
if err != nil {
|
||||
l.Error("[QueryDocumentList] error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "QueryDocumentList error: %v", err.Error())
|
||||
}
|
||||
resp = &types.QueryDocumentListResponse{
|
||||
Total: total,
|
||||
List: make([]types.Document, 0),
|
||||
}
|
||||
for _, item := range data {
|
||||
resp.List = append(resp.List, types.Document{
|
||||
Id: item.Id,
|
||||
Title: item.Title,
|
||||
Tags: tool.StringMergeAndRemoveDuplicates(item.Tags),
|
||||
UpdatedAt: item.UpdatedAt.UnixMilli(),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type GetNodeListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get Node list
|
||||
func NewGetNodeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetNodeListLogic {
|
||||
return &GetNodeListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetNodeListLogic) GetNodeList(req *types.AppUserSubscbribeNodeRequest) (resp *types.AppUserSubscbribeNodeResponse, err error) {
|
||||
resp = &types.AppUserSubscbribeNodeResponse{List: make([]types.AppUserSubscbribeNode, 0)}
|
||||
userInfo := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
userSubscribe, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find user subscribe: %v", err.Error())
|
||||
}
|
||||
|
||||
if userInfo.Id != userSubscribe.UserId {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "find user subscribe: %v", err.Error())
|
||||
}
|
||||
|
||||
//拿到所有订阅下的服务组id
|
||||
var ids []int64
|
||||
for _, idStr := range strings.Split(userSubscribe.Subscribe.ServerGroup, ",") {
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
//根据服务组id拿到所有节点
|
||||
servers, err := l.svcCtx.ServerModel.FindServerListByGroupIds(l.ctx, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, server := range servers {
|
||||
resp.List = append(resp.List, types.AppUserSubscbribeNode{
|
||||
Id: server.Id,
|
||||
Uuid: userSubscribe.UUID,
|
||||
Traffic: userSubscribe.Traffic,
|
||||
Upload: userSubscribe.Upload,
|
||||
Download: userSubscribe.Download,
|
||||
RelayNode: server.RelayNode,
|
||||
RelayMode: server.RelayMode,
|
||||
Longitude: server.Longitude,
|
||||
Latitude: server.Latitude,
|
||||
Tags: strings.Split(server.Tags, ","),
|
||||
Config: server.Config,
|
||||
ServerAddr: server.ServerAddr,
|
||||
Protocol: server.Protocol,
|
||||
SpeedLimit: server.SpeedLimit,
|
||||
City: server.City,
|
||||
Country: server.Country,
|
||||
Name: server.Name,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package node
|
||||
|
||||
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/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GetRuleGroupListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get rule group list
|
||||
func NewGetRuleGroupListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetRuleGroupListLogic {
|
||||
return &GetRuleGroupListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetRuleGroupListLogic) GetRuleGroupList() (resp *types.AppRuleGroupListResponse, err error) {
|
||||
nodeRuleGroupList, err := l.svcCtx.ServerModel.QueryAllRuleGroup(l.ctx)
|
||||
if err != nil {
|
||||
l.Logger.Error("[GetRuleGroupList] get subscribe rule group list failed: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get subscribe rule group list failed: %v", err.Error())
|
||||
}
|
||||
nodeRuleGroups := make([]types.ServerRuleGroup, 0)
|
||||
tool.DeepCopy(&nodeRuleGroups, nodeRuleGroupList)
|
||||
return &types.AppRuleGroupListResponse{
|
||||
Total: int64(len(nodeRuleGroups)),
|
||||
List: nodeRuleGroups,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/perfect-panel/server/internal/model/coupon"
|
||||
)
|
||||
|
||||
func calculateCoupon(amount int64, couponInfo *coupon.Coupon) int64 {
|
||||
if couponInfo.Type == 1 {
|
||||
return int64(float64(amount) * (float64(couponInfo.Discount) / float64(100)))
|
||||
} else {
|
||||
return min(couponInfo.Discount, amount)
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package order
|
||||
|
||||
import "github.com/perfect-panel/server/internal/model/payment"
|
||||
|
||||
func calculateFee(amount int64, config *payment.Payment) int64 {
|
||||
var fee float64
|
||||
switch config.FeeMode {
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
fee = float64(amount) * (float64(config.FeePercent) / float64(100))
|
||||
case 2:
|
||||
if amount > 0 {
|
||||
fee = float64(config.FeeAmount)
|
||||
}
|
||||
case 3:
|
||||
fee = float64(amount)*(float64(config.FeePercent)/float64(100)) + float64(config.FeeAmount)
|
||||
}
|
||||
return int64(fee)
|
||||
}
|
||||
@@ -1,325 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
paymentPlatform "github.com/perfect-panel/server/pkg/payment"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/payment"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/exchangeRate"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/payment/alipay"
|
||||
"github.com/perfect-panel/server/pkg/payment/epay"
|
||||
"github.com/perfect-panel/server/pkg/payment/stripe"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
queueType "github.com/perfect-panel/server/queue/types"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CheckoutOrderLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
type CurrencyConfig struct {
|
||||
CurrencyUnit string
|
||||
CurrencySymbol string
|
||||
AccessKey string
|
||||
}
|
||||
|
||||
const (
|
||||
Stripe = "Stripe"
|
||||
QR = "qr"
|
||||
Link = "link"
|
||||
)
|
||||
|
||||
// NewCheckoutOrderLogic Checkout order
|
||||
func NewCheckoutOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckoutOrderLogic {
|
||||
return &CheckoutOrderLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CheckoutOrderLogic) CheckoutOrder(req *types.CheckoutOrderRequest, requestHost string) (resp *types.CheckoutOrderResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
l.Error("[CheckoutOrderLogic] Invalid access")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid access")
|
||||
}
|
||||
// find order
|
||||
orderInfo, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] FindOneByOrderNo error", logger.Field("orderNo", req.OrderNo), logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "FindOneByOrderNo error: %s", err.Error())
|
||||
}
|
||||
|
||||
if orderInfo.Status != 1 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "Order status error")
|
||||
}
|
||||
|
||||
paymentConfig, err := l.svcCtx.PaymentModel.FindOne(l.ctx, orderInfo.PaymentId)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] FindOneByPaymentMark error", logger.Field("paymentMark", orderInfo.Method), logger.Field("PaymentID", orderInfo.PaymentId), logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "FindOneByPaymentMark error: %s", err.Error())
|
||||
}
|
||||
var stripePayment *types.StripePayment = nil
|
||||
var url, t string
|
||||
|
||||
// switch payment method
|
||||
switch paymentPlatform.ParsePlatform(paymentConfig.Platform) {
|
||||
case paymentPlatform.Stripe:
|
||||
result, err := l.stripePayment(paymentConfig.Config, orderInfo, u)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] stripePayment error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
stripePayment = result
|
||||
t = Stripe
|
||||
case paymentPlatform.EPay:
|
||||
// epay
|
||||
url, err = l.epayPayment(paymentConfig, orderInfo, req.ReturnUrl, requestHost)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] epayPayment error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
t = Link
|
||||
case paymentPlatform.AlipayF2F:
|
||||
// alipay f2f
|
||||
url, err = l.alipayF2fPayment(paymentConfig, orderInfo, requestHost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t = QR
|
||||
case paymentPlatform.Balance:
|
||||
// balance
|
||||
if err = l.balancePayment(u, orderInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t = paymentPlatform.Balance.String()
|
||||
default:
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "Payment method not supported")
|
||||
}
|
||||
return &types.CheckoutOrderResponse{
|
||||
Type: t,
|
||||
CheckoutUrl: url,
|
||||
Stripe: stripePayment,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Query exchange rate
|
||||
func (l *CheckoutOrderLogic) queryExchangeRate(to string, src int64) (amount float64, err error) {
|
||||
amount = float64(src) / float64(100)
|
||||
// query system currency
|
||||
currency, err := l.svcCtx.SystemModel.GetCurrencyConfig(l.ctx)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] GetCurrencyConfig error", logger.Field("error", err.Error()))
|
||||
return 0, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "GetCurrencyConfig error: %s", err.Error())
|
||||
}
|
||||
configs := &CurrencyConfig{}
|
||||
tool.SystemConfigSliceReflectToStruct(currency, configs)
|
||||
if configs.AccessKey == "" {
|
||||
return amount, nil
|
||||
}
|
||||
if configs.CurrencyUnit != to {
|
||||
// query exchange rate
|
||||
result, err := exchangeRate.GetExchangeRete(configs.CurrencyUnit, to, configs.AccessKey, 1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
amount = result * amount
|
||||
}
|
||||
return amount, nil
|
||||
}
|
||||
|
||||
// Stripe Payment
|
||||
func (l *CheckoutOrderLogic) stripePayment(config string, info *order.Order, u *user.User) (*types.StripePayment, error) {
|
||||
// stripe WeChat pay or stripe alipay
|
||||
stripeConfig := payment.StripeConfig{}
|
||||
if err := json.Unmarshal([]byte(config), &stripeConfig); err != nil {
|
||||
l.Error("[CheckoutOrderLogic] Unmarshal error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "Unmarshal error: %s", err.Error())
|
||||
}
|
||||
client := stripe.NewClient(stripe.Config{
|
||||
SecretKey: stripeConfig.SecretKey,
|
||||
PublicKey: stripeConfig.PublicKey,
|
||||
WebhookSecret: stripeConfig.WebhookSecret,
|
||||
})
|
||||
// Calculate the amount with exchange rate
|
||||
amount, err := l.queryExchangeRate("CNY", info.Amount)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] queryExchangeRate error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "queryExchangeRate error: %s", err.Error())
|
||||
}
|
||||
convertAmount := int64(amount * 100)
|
||||
// create payment
|
||||
result, err := client.CreatePaymentSheet(&stripe.Order{
|
||||
OrderNo: info.OrderNo,
|
||||
Subscribe: strconv.FormatInt(info.SubscribeId, 10),
|
||||
Amount: convertAmount,
|
||||
Currency: "cny",
|
||||
Payment: stripeConfig.Payment,
|
||||
},
|
||||
&stripe.User{
|
||||
UserId: u.Id,
|
||||
})
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] CreatePaymentSheet error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "CreatePaymentSheet error: %s", err.Error())
|
||||
}
|
||||
tradeNo := result.TradeNo
|
||||
stripePayment := &types.StripePayment{
|
||||
PublishableKey: stripeConfig.PublicKey,
|
||||
ClientSecret: result.ClientSecret,
|
||||
Method: stripeConfig.Payment,
|
||||
}
|
||||
// save payment
|
||||
info.TradeNo = tradeNo
|
||||
err = l.svcCtx.OrderModel.Update(l.ctx, info)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] Update error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "Update error: %s", err.Error())
|
||||
}
|
||||
return stripePayment, nil
|
||||
}
|
||||
|
||||
// epay payment
|
||||
func (l *CheckoutOrderLogic) epayPayment(config *payment.Payment, info *order.Order, returnUrl, requestHost string) (string, error) {
|
||||
epayConfig := payment.EPayConfig{}
|
||||
if err := json.Unmarshal([]byte(config.Config), &epayConfig); err != nil {
|
||||
l.Error("[CheckoutOrderLogic] Unmarshal error", logger.Field("error", err.Error()))
|
||||
return "", errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "Unmarshal error: %s", err.Error())
|
||||
}
|
||||
client := epay.NewClient(epayConfig.Pid, epayConfig.Url, epayConfig.Key)
|
||||
// Calculate the amount with exchange rate
|
||||
amount, err := l.queryExchangeRate("CNY", info.Amount)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var domain string
|
||||
if config.Domain != "" {
|
||||
domain = config.Domain
|
||||
} else {
|
||||
domain = fmt.Sprintf("http://%s", requestHost)
|
||||
}
|
||||
// create payment
|
||||
url := client.CreatePayUrl(epay.Order{
|
||||
Name: l.svcCtx.Config.Site.SiteName,
|
||||
Amount: amount,
|
||||
OrderNo: info.OrderNo,
|
||||
SignType: "MD5",
|
||||
NotifyUrl: domain + "/v1/notify/epay",
|
||||
ReturnUrl: returnUrl,
|
||||
})
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// alipay f2f payment
|
||||
func (l *CheckoutOrderLogic) alipayF2fPayment(pay *payment.Payment, info *order.Order, requestHost string) (string, error) {
|
||||
f2FConfig := payment.AlipayF2FConfig{}
|
||||
if err := json.Unmarshal([]byte(pay.Config), &f2FConfig); err != nil {
|
||||
l.Error("[CheckoutOrderLogic] Unmarshal error", logger.Field("error", err.Error()))
|
||||
return "", errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "Unmarshal error: %s", err.Error())
|
||||
}
|
||||
var domain string
|
||||
if pay.Domain != "" {
|
||||
domain = pay.Domain
|
||||
} else {
|
||||
domain = fmt.Sprintf("http://%s", requestHost)
|
||||
}
|
||||
client := alipay.NewClient(alipay.Config{
|
||||
AppId: f2FConfig.AppId,
|
||||
PrivateKey: f2FConfig.PrivateKey,
|
||||
PublicKey: f2FConfig.PublicKey,
|
||||
InvoiceName: f2FConfig.InvoiceName,
|
||||
NotifyURL: domain + "/notify/alipay",
|
||||
})
|
||||
// Calculate the amount with exchange rate
|
||||
amount, err := l.queryExchangeRate("CNY", info.Amount)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] queryExchangeRate error", logger.Field("error", err.Error()))
|
||||
return "", errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "queryExchangeRate error: %s", err.Error())
|
||||
}
|
||||
convertAmount := int64(amount * 100)
|
||||
// create payment
|
||||
QRCode, err := client.PreCreateTrade(l.ctx, alipay.Order{
|
||||
OrderNo: info.OrderNo,
|
||||
Amount: convertAmount,
|
||||
})
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] PreCreateTrade error", logger.Field("error", err.Error()))
|
||||
return "", errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "PreCreateTrade error: %s", err.Error())
|
||||
}
|
||||
return QRCode, nil
|
||||
}
|
||||
|
||||
// Balance payment
|
||||
func (l *CheckoutOrderLogic) balancePayment(u *user.User, o *order.Order) error {
|
||||
var userInfo user.User
|
||||
err := l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
|
||||
err := db.Model(&user.User{}).Where("id = ?", u.Id).First(&userInfo).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if userInfo.Balance < o.Amount {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.InsufficientBalance), "Insufficient balance")
|
||||
}
|
||||
// deduct balance
|
||||
userInfo.Balance -= o.Amount
|
||||
err = l.svcCtx.UserModel.Update(l.ctx, &userInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// create balance log
|
||||
balanceLog := &user.BalanceLog{
|
||||
Id: 0,
|
||||
UserId: u.Id,
|
||||
Amount: o.Amount,
|
||||
Type: 3,
|
||||
OrderId: o.Id,
|
||||
Balance: userInfo.Balance,
|
||||
}
|
||||
err = db.Create(balanceLog).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return l.svcCtx.OrderModel.UpdateOrderStatus(l.ctx, o.OrderNo, 2)
|
||||
})
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] Transaction error", logger.Field("error", err.Error()), logger.Field("orderNo", o.OrderNo))
|
||||
return err
|
||||
}
|
||||
// create activity order task
|
||||
payload := queueType.ForthwithActivateOrderPayload{
|
||||
OrderNo: o.OrderNo,
|
||||
}
|
||||
bytes, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] Marshal error", logger.Field("error", err.Error()))
|
||||
return err
|
||||
}
|
||||
|
||||
task := asynq.NewTask(queueType.ForthwithActivateOrder, bytes)
|
||||
_, err = l.svcCtx.Queue.EnqueueContext(l.ctx, task)
|
||||
if err != nil {
|
||||
l.Error("[CheckoutOrderLogic] Enqueue error", logger.Field("error", err.Error()))
|
||||
return err
|
||||
}
|
||||
l.Logger.Info("[CheckoutOrderLogic] Enqueue success", logger.Field("orderNo", o.OrderNo))
|
||||
return nil
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
paymentPlatform "github.com/perfect-panel/server/pkg/payment"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/pkg/payment/stripe"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/payment"
|
||||
"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/payment/alipay"
|
||||
)
|
||||
|
||||
type CloseOrderLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewCloseOrderLogic Close order
|
||||
func NewCloseOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CloseOrderLogic {
|
||||
return &CloseOrderLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CloseOrderLogic) CloseOrder(req *types.CloseOrderRequest) error {
|
||||
// Find order information by order number
|
||||
orderInfo, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
|
||||
if err != nil {
|
||||
l.Error("[CloseOrder] Find order info failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("orderNo", req.OrderNo),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
// If the order status is not 1, it means that the order has been closed or paid
|
||||
if orderInfo.Status != 1 {
|
||||
l.Info("[CloseOrder] Order status is not 1",
|
||||
logger.Field("orderNo", req.OrderNo),
|
||||
logger.Field("status", orderInfo.Status),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
if l.confirmationPayment(orderInfo) {
|
||||
l.Info("[CloseOrder] Order has been paid",
|
||||
logger.Field("orderNo", req.OrderNo),
|
||||
logger.Field("status", orderInfo.Status),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
err = l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
|
||||
// update order status
|
||||
err := tx.Model(&order.Order{}).Where("order_no = ?", req.OrderNo).Update("status", 3).Error
|
||||
if err != nil {
|
||||
l.Error("[CloseOrder] Update order status failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("orderNo", req.OrderNo),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// refund deduction amount to user deduction balance
|
||||
if orderInfo.GiftAmount > 0 {
|
||||
userInfo, err := l.svcCtx.UserModel.FindOne(l.ctx, orderInfo.UserId)
|
||||
if err != nil {
|
||||
l.Error("[CloseOrder] Find user info failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", orderInfo.UserId),
|
||||
)
|
||||
return err
|
||||
}
|
||||
deduction := userInfo.GiftAmount + orderInfo.GiftAmount
|
||||
err = tx.Model(&user.User{}).Where("id = ?", orderInfo.UserId).Update("deduction", deduction).Error
|
||||
if err != nil {
|
||||
l.Error("[CloseOrder] Refund deduction amount failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("uid", orderInfo.UserId),
|
||||
logger.Field("deduction", orderInfo.GiftAmount),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// Record the deduction refund log
|
||||
giftAmountLog := &user.GiftAmountLog{
|
||||
UserId: orderInfo.UserId,
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
Amount: orderInfo.GiftAmount,
|
||||
Type: 1,
|
||||
Balance: deduction,
|
||||
Remark: "Order cancellation refund",
|
||||
}
|
||||
err = tx.Model(&user.GiftAmountLog{}).Create(giftAmountLog).Error
|
||||
if err != nil {
|
||||
l.Error("[CloseOrder] Record cancellation refund log failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("uid", orderInfo.UserId),
|
||||
logger.Field("deduction", orderInfo.GiftAmount),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// update user cache
|
||||
return l.svcCtx.UserModel.UpdateUserCache(l.ctx, userInfo)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// confirmationPayment Determine whether the payment is successful
|
||||
//
|
||||
//nolint:unused
|
||||
func (l *CloseOrderLogic) confirmationPayment(order *order.Order) bool {
|
||||
paymentConfig, err := l.svcCtx.PaymentModel.FindOne(l.ctx, order.PaymentId)
|
||||
if err != nil {
|
||||
l.Error("[CloseOrder] Find payment config failed", logger.Field("error", err.Error()), logger.Field("paymentMark", order.Method))
|
||||
return false
|
||||
}
|
||||
switch paymentPlatform.ParsePlatform(order.Method) {
|
||||
case paymentPlatform.AlipayF2F:
|
||||
if l.queryAlipay(paymentConfig, order.TradeNo) {
|
||||
return true
|
||||
}
|
||||
case paymentPlatform.Stripe:
|
||||
if l.queryStripe(paymentConfig, order.TradeNo) {
|
||||
return true
|
||||
}
|
||||
default:
|
||||
l.Info("[CloseOrder] Unsupported payment method", logger.Field("paymentMethod", order.Method))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// queryAlipay Query Alipay payment status
|
||||
func (l *CloseOrderLogic) queryAlipay(paymentConfig *payment.Payment, TradeNo string) bool {
|
||||
config := payment.AlipayF2FConfig{}
|
||||
if err := json.Unmarshal([]byte(paymentConfig.Config), &config); err != nil {
|
||||
l.Error("[CloseOrder] Unmarshal payment config failed", logger.Field("error", err.Error()), logger.Field("config", paymentConfig.Config))
|
||||
return false
|
||||
}
|
||||
client := alipay.NewClient(alipay.Config{
|
||||
AppId: config.AppId,
|
||||
PrivateKey: config.PrivateKey,
|
||||
PublicKey: config.PublicKey,
|
||||
InvoiceName: config.InvoiceName,
|
||||
})
|
||||
status, err := client.QueryTrade(l.ctx, TradeNo)
|
||||
if err != nil {
|
||||
l.Error("[CloseOrder] Query trade failed", logger.Field("error", err.Error()), logger.Field("TradeNo", TradeNo))
|
||||
return false
|
||||
}
|
||||
if status == alipay.Success || status == alipay.Finished {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// queryStripe Query Stripe payment status
|
||||
func (l *CloseOrderLogic) queryStripe(paymentConfig *payment.Payment, TradeNo string) bool {
|
||||
config := payment.StripeConfig{}
|
||||
if err := json.Unmarshal([]byte(paymentConfig.Config), &config); err != nil {
|
||||
l.Error("[CloseOrder] Unmarshal payment config failed", logger.Field("error", err.Error()), logger.Field("config", paymentConfig.Config))
|
||||
return false
|
||||
}
|
||||
client := stripe.NewClient(stripe.Config{
|
||||
PublicKey: config.PublicKey,
|
||||
SecretKey: config.SecretKey,
|
||||
WebhookSecret: config.WebhookSecret,
|
||||
})
|
||||
status, err := client.QueryOrderStatus(TradeNo)
|
||||
if err != nil {
|
||||
l.Error("[CloseOrder] Query order status failed", logger.Field("error", err.Error()), logger.Field("TradeNo", TradeNo))
|
||||
return false
|
||||
}
|
||||
return status
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package order
|
||||
|
||||
import "github.com/perfect-panel/server/internal/types"
|
||||
|
||||
func getDiscount(discounts []types.SubscribeDiscount, inputMonths int64) float64 {
|
||||
var finalDiscount int64 = 100
|
||||
|
||||
for _, discount := range discounts {
|
||||
if inputMonths >= discount.Quantity && discount.Discount < finalDiscount {
|
||||
finalDiscount = discount.Discount
|
||||
}
|
||||
}
|
||||
return float64(finalDiscount) / float64(100)
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"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 PreCreateOrderLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Pre create order
|
||||
func NewPreCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PreCreateOrderLogic {
|
||||
return &PreCreateOrderLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PreCreateOrderLogic) PreCreateOrder(req *types.PurchaseOrderRequest) (resp *types.PreOrderResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
// find subscribe plan
|
||||
sub, err := l.svcCtx.SubscribeModel.FindOne(l.ctx, req.SubscribeId)
|
||||
if err != nil {
|
||||
l.Error("[PreCreateOrder] Database query error", logger.Field("error", err.Error()), logger.Field("subscribe_id", req.SubscribeId))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find subscribe error: %v", err.Error())
|
||||
}
|
||||
var discount float64 = 1
|
||||
if sub.Discount != "" {
|
||||
var dis []types.SubscribeDiscount
|
||||
_ = json.Unmarshal([]byte(sub.Discount), &dis)
|
||||
discount = getDiscount(dis, req.Quantity)
|
||||
}
|
||||
price := sub.UnitPrice * req.Quantity
|
||||
amount := int64(float64(price) * discount)
|
||||
discountAmount := price - amount
|
||||
var coupon int64
|
||||
if req.Coupon != "" {
|
||||
couponInfo, err := l.svcCtx.CouponModel.FindOneByCode(l.ctx, req.Coupon)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponNotExist), "coupon not found")
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find coupon error: %v", err.Error())
|
||||
}
|
||||
if couponInfo.Count > 0 && couponInfo.Count <= couponInfo.UsedCount {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponInsufficientUsage), "coupon used")
|
||||
}
|
||||
couponSub := tool.StringToInt64Slice(couponInfo.Subscribe)
|
||||
if len(couponSub) > 0 && !tool.Contains(couponSub, req.SubscribeId) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponNotApplicable), "coupon not match")
|
||||
}
|
||||
var count int64
|
||||
err = l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
|
||||
return tx.Model(&order.Order{}).Where("user_id = ? and coupon = ?", u.Id, req.Coupon).Count(&count).Error
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorw("[Purchase] Database query error", logger.Field("error", err.Error()), logger.Field("user_id", u.Id), logger.Field("coupon", req.Coupon))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find coupon error: %v", err.Error())
|
||||
}
|
||||
if couponInfo.UserLimit > 0 && count >= couponInfo.UserLimit {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponInsufficientUsage), "coupon limit exceeded")
|
||||
}
|
||||
coupon = calculateCoupon(amount, couponInfo)
|
||||
}
|
||||
amount -= coupon
|
||||
|
||||
var deductionAmount int64
|
||||
// Check user deduction amount
|
||||
if u.GiftAmount > 0 {
|
||||
if u.GiftAmount >= amount {
|
||||
deductionAmount = amount
|
||||
amount = 0
|
||||
} else {
|
||||
deductionAmount = u.GiftAmount
|
||||
amount -= u.GiftAmount
|
||||
}
|
||||
}
|
||||
|
||||
payment, err := l.svcCtx.PaymentModel.FindOne(l.ctx, req.Payment)
|
||||
if err != nil {
|
||||
l.Logger.Error("[PreCreateOrder] Database query error", logger.Field("error", err.Error()), logger.Field("payment", req.Payment))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find payment method error: %v", err.Error())
|
||||
}
|
||||
var feeAmount int64
|
||||
// Calculate the handling fee
|
||||
if amount > 0 {
|
||||
feeAmount = calculateFee(amount, payment)
|
||||
}
|
||||
amount += feeAmount
|
||||
|
||||
resp = &types.PreOrderResponse{
|
||||
Price: price,
|
||||
Amount: amount,
|
||||
Discount: discountAmount,
|
||||
GiftAmount: deductionAmount,
|
||||
Coupon: req.Coupon,
|
||||
CouponDiscount: coupon,
|
||||
FeeAmount: feeAmount,
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"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"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PurchaseLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
const CloseOrderTimeMinutes = 15
|
||||
|
||||
// purchase Subscription
|
||||
func NewPurchaseLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PurchaseLogic {
|
||||
return &PurchaseLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.PurchaseOrderResponse, err error) {
|
||||
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
// find user subscription
|
||||
|
||||
if l.svcCtx.Config.Subscribe.SingleModel {
|
||||
userSub, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, u.Id)
|
||||
if err != nil {
|
||||
l.Error("[Purchase] Database query error", logger.Field("error", err.Error()), logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find user subscription error: %v", err.Error())
|
||||
}
|
||||
if len(userSub) > 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.UserSubscribeExist), "user has subscription")
|
||||
}
|
||||
}
|
||||
|
||||
// find subscribe plan
|
||||
sub, err := l.svcCtx.SubscribeModel.FindOne(l.ctx, req.SubscribeId)
|
||||
|
||||
if err != nil {
|
||||
l.Error("[Purchase] Database query error", logger.Field("error", err.Error()), logger.Field("subscribe_id", req.SubscribeId))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find subscribe error: %v", err.Error())
|
||||
}
|
||||
// check subscribe plan status
|
||||
if !*sub.Sell {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "subscribe not sell")
|
||||
}
|
||||
var discount float64 = 1
|
||||
if sub.Discount != "" {
|
||||
var dis []types.SubscribeDiscount
|
||||
_ = json.Unmarshal([]byte(sub.Discount), &dis)
|
||||
discount = getDiscount(dis, req.Quantity)
|
||||
}
|
||||
price := sub.UnitPrice * req.Quantity
|
||||
// discount amount
|
||||
amount := int64(float64(price) * discount)
|
||||
discountAmount := price - amount
|
||||
var coupon int64 = 0
|
||||
// Calculate the coupon deduction
|
||||
if req.Coupon != "" {
|
||||
couponInfo, err := l.svcCtx.CouponModel.FindOneByCode(l.ctx, req.Coupon)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponNotExist), "coupon not found")
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find coupon error: %v", err.Error())
|
||||
}
|
||||
if couponInfo.Count <= couponInfo.UsedCount {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponInsufficientUsage), "coupon used")
|
||||
}
|
||||
couponSub := tool.StringToInt64Slice(couponInfo.Subscribe)
|
||||
if len(couponSub) > 0 && !tool.Contains(couponSub, req.SubscribeId) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponNotApplicable), "coupon not match")
|
||||
}
|
||||
var count int64
|
||||
err = l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
|
||||
return tx.Model(&order.Order{}).Where("user_id = ? and coupon = ?", u.Id, req.Coupon).Count(&count).Error
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorw("[Purchase] Database query error", logger.Field("error", err.Error()), logger.Field("user_id", u.Id), logger.Field("coupon", req.Coupon))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find coupon error: %v", err.Error())
|
||||
}
|
||||
if count >= couponInfo.UserLimit {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponInsufficientUsage), "coupon limit exceeded")
|
||||
}
|
||||
coupon = calculateCoupon(amount, couponInfo)
|
||||
}
|
||||
// Calculate the handling fee
|
||||
amount -= coupon
|
||||
var deductionAmount int64
|
||||
// Check user deduction amount
|
||||
if u.GiftAmount > 0 {
|
||||
if u.GiftAmount >= amount {
|
||||
deductionAmount = amount
|
||||
amount = 0
|
||||
u.GiftAmount -= amount
|
||||
} else {
|
||||
deductionAmount = u.GiftAmount
|
||||
amount -= u.GiftAmount
|
||||
u.GiftAmount = 0
|
||||
}
|
||||
}
|
||||
// find payment method
|
||||
payment, err := l.svcCtx.PaymentModel.FindOne(l.ctx, req.Payment)
|
||||
if err != nil {
|
||||
l.Logger.Error("[Purchase] Database query error", logger.Field("error", err.Error()), logger.Field("payment", req.Payment))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find payment method error: %v", err.Error())
|
||||
}
|
||||
var feeAmount int64
|
||||
// Calculate the handling fee
|
||||
if amount > 0 {
|
||||
feeAmount = calculateFee(amount, payment)
|
||||
}
|
||||
// query user is new purchase or renewal
|
||||
isNew, err := l.svcCtx.OrderModel.IsUserEligibleForNewOrder(l.ctx, u.Id)
|
||||
if err != nil {
|
||||
l.Error("[Purchase] Database query error", logger.Field("error", err.Error()), logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find user order error: %v", err.Error())
|
||||
}
|
||||
// create order
|
||||
orderInfo := &order.Order{
|
||||
UserId: u.Id,
|
||||
OrderNo: tool.GenerateTradeNo(),
|
||||
Type: 1,
|
||||
Quantity: req.Quantity,
|
||||
Price: price,
|
||||
Amount: amount,
|
||||
Discount: discountAmount,
|
||||
GiftAmount: deductionAmount,
|
||||
Coupon: req.Coupon,
|
||||
CouponDiscount: coupon,
|
||||
PaymentId: req.Payment,
|
||||
Method: payment.Platform,
|
||||
FeeAmount: feeAmount,
|
||||
Status: 1,
|
||||
IsNew: isNew,
|
||||
SubscribeId: req.SubscribeId,
|
||||
}
|
||||
// Database transaction
|
||||
err = l.svcCtx.DB.Transaction(func(db *gorm.DB) error {
|
||||
// update user deduction && Pre deduction ,Return after canceling the order
|
||||
if orderInfo.GiftAmount > 0 {
|
||||
// update user deduction && Pre deduction ,Return after canceling the order
|
||||
if e := l.svcCtx.UserModel.Update(l.ctx, u, db); err != nil {
|
||||
l.Error("[Purchase] Database update error", logger.Field("error", err.Error()), logger.Field("user", u))
|
||||
return e
|
||||
}
|
||||
// create deduction record
|
||||
giftAmountLog := user.GiftAmountLog{
|
||||
UserId: orderInfo.UserId,
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
Amount: orderInfo.GiftAmount,
|
||||
Type: 2,
|
||||
Balance: u.GiftAmount,
|
||||
Remark: "Purchase order deduction",
|
||||
}
|
||||
if e := db.Model(&user.GiftAmountLog{}).Create(&giftAmountLog).Error; e != nil {
|
||||
l.Error("[Purchase] Database insert error",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("deductionLog", giftAmountLog),
|
||||
)
|
||||
return e
|
||||
}
|
||||
}
|
||||
// insert order
|
||||
return db.Model(&order.Order{}).Create(&orderInfo).Error
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "insert order error: %v", err.Error())
|
||||
}
|
||||
// Deferred task
|
||||
payload := queue.DeferCloseOrderPayload{
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
}
|
||||
val, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
l.Error("[CreateOrder] Marshal payload error", logger.Field("error", err.Error()), logger.Field("payload", payload))
|
||||
}
|
||||
task := asynq.NewTask(queue.DeferCloseOrder, val, asynq.MaxRetry(3))
|
||||
taskInfo, err := l.svcCtx.Queue.Enqueue(task, asynq.ProcessIn(CloseOrderTimeMinutes*time.Minute))
|
||||
if err != nil {
|
||||
l.Error("[CreateOrder] Enqueue task error", logger.Field("error", err.Error()), logger.Field("task", task))
|
||||
} else {
|
||||
l.Info("[CreateOrder] Enqueue task success", logger.Field("TaskID", taskInfo.ID))
|
||||
}
|
||||
|
||||
return &types.PurchaseOrderResponse{
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package order
|
||||
|
||||
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/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type QueryOrderDetailLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get order
|
||||
func NewQueryOrderDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryOrderDetailLogic {
|
||||
return &QueryOrderDetailLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryOrderDetailLogic) QueryOrderDetail(req *types.QueryOrderDetailRequest) (resp *types.OrderDetail, err error) {
|
||||
orderInfo, err := l.svcCtx.OrderModel.FindOneDetailsByOrderNo(l.ctx, req.OrderNo)
|
||||
if err != nil {
|
||||
l.Error("[QueryOrderDetail] Database query error", logger.Field("error", err.Error()), logger.Field("order_no", req.OrderNo))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find order error: %v", err.Error())
|
||||
}
|
||||
resp = &types.OrderDetail{}
|
||||
tool.DeepCopy(resp, orderInfo)
|
||||
// Prevent commission amount leakage
|
||||
resp.Commission = 0
|
||||
return
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"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 QueryOrderListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get order list
|
||||
func NewQueryOrderListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryOrderListLogic {
|
||||
return &QueryOrderListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryOrderListLogic) QueryOrderList(req *types.QueryOrderListRequest) (resp *types.QueryOrderListResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
total, data, err := l.svcCtx.OrderModel.QueryOrderListByPage(l.ctx, req.Page, req.Size, 0, u.Id, 0, "")
|
||||
if err != nil {
|
||||
l.Error("[QueryOrderListLogic] Query order list failed", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "Query order list failed")
|
||||
}
|
||||
resp = &types.QueryOrderListResponse{
|
||||
Total: total,
|
||||
List: make([]types.OrderDetail, 0),
|
||||
}
|
||||
for _, item := range data {
|
||||
var orderInfo types.OrderDetail
|
||||
tool.DeepCopy(&orderInfo, item)
|
||||
// Prevent commission amount leakage
|
||||
orderInfo.Commission = 0
|
||||
resp.List = append(resp.List, orderInfo)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"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"
|
||||
queue "github.com/perfect-panel/server/queue/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type RechargeLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewRechargeLogic Recharge
|
||||
func NewRechargeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RechargeLogic {
|
||||
return &RechargeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *RechargeLogic) Recharge(req *types.RechargeOrderRequest) (resp *types.RechargeOrderResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
// find payment method
|
||||
payment, err := l.svcCtx.PaymentModel.FindOne(l.ctx, req.Payment)
|
||||
if err != nil {
|
||||
l.Error("[Recharge] Database query error", logger.Field("error", err.Error()), logger.Field("payment", req.Payment))
|
||||
return nil, errors.Wrapf(err, "find payment error: %v", err.Error())
|
||||
}
|
||||
// Calculate the handling fee
|
||||
feeAmount := calculateFee(req.Amount, payment)
|
||||
// query user is new purchase or renewal
|
||||
isNew, err := l.svcCtx.OrderModel.IsUserEligibleForNewOrder(l.ctx, u.Id)
|
||||
if err != nil {
|
||||
l.Error("[Recharge] Database query error", logger.Field("error", err.Error()), logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(err, "query user error: %v", err.Error())
|
||||
}
|
||||
orderInfo := order.Order{
|
||||
UserId: u.Id,
|
||||
OrderNo: tool.GenerateTradeNo(),
|
||||
Type: 4,
|
||||
Price: req.Amount,
|
||||
Amount: req.Amount + feeAmount,
|
||||
FeeAmount: feeAmount,
|
||||
PaymentId: req.Payment,
|
||||
Method: payment.Platform,
|
||||
Status: 1,
|
||||
IsNew: isNew,
|
||||
}
|
||||
err = l.svcCtx.OrderModel.Insert(l.ctx, &orderInfo)
|
||||
if err != nil {
|
||||
l.Error("[Recharge] Database insert error", logger.Field("error", err.Error()), logger.Field("order", orderInfo))
|
||||
return nil, errors.Wrapf(err, "insert order error: %v", err.Error())
|
||||
}
|
||||
// Deferred task
|
||||
payload := queue.DeferCloseOrderPayload{
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
}
|
||||
val, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
l.Error("[Recharge] Marshal payload error", logger.Field("error", err.Error()), logger.Field("payload", payload))
|
||||
}
|
||||
task := asynq.NewTask(queue.DeferCloseOrder, val, asynq.MaxRetry(3))
|
||||
taskInfo, err := l.svcCtx.Queue.Enqueue(task, asynq.ProcessIn(CloseOrderTimeMinutes*time.Minute))
|
||||
if err != nil {
|
||||
l.Error("[Recharge] Enqueue task error", logger.Field("error", err.Error()), logger.Field("task", task))
|
||||
} else {
|
||||
l.Info("[Recharge] Enqueue task success", logger.Field("TaskID", taskInfo.ID))
|
||||
}
|
||||
return &types.RechargeOrderResponse{
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"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"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type RenewalLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Renewal Subscription
|
||||
func NewRenewalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RenewalLogic {
|
||||
return &RenewalLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *RenewalLogic) Renewal(req *types.RenewalOrderRequest) (resp *types.RenewalOrderResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
orderNo := tool.GenerateTradeNo()
|
||||
// find user subscribe
|
||||
userSubscribe, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, req.UserSubscribeID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find user subscribe error: %v", err.Error())
|
||||
}
|
||||
// find subscription
|
||||
sub, err := l.svcCtx.SubscribeModel.FindOne(l.ctx, userSubscribe.SubscribeId)
|
||||
if err != nil {
|
||||
l.Error("[Renewal] Database query error", logger.Field("error", err.Error()), logger.Field("subscribe_id", userSubscribe.SubscribeId))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find subscribe error: %v", err.Error())
|
||||
}
|
||||
// check subscribe plan status
|
||||
if !*sub.Sell {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "subscribe not sell")
|
||||
}
|
||||
var discount float64 = 1
|
||||
if sub.Discount != "" {
|
||||
var dis []types.SubscribeDiscount
|
||||
_ = json.Unmarshal([]byte(sub.Discount), &dis)
|
||||
discount = getDiscount(dis, req.Quantity)
|
||||
}
|
||||
price := sub.UnitPrice * req.Quantity
|
||||
amount := int64(float64(price) * discount)
|
||||
discountAmount := price - amount
|
||||
var coupon int64 = 0
|
||||
if req.Coupon != "" {
|
||||
couponInfo, err := l.svcCtx.CouponModel.FindOneByCode(l.ctx, req.Coupon)
|
||||
if err != nil {
|
||||
l.Error("[Renewal] Database query error", logger.Field("error", err.Error()), logger.Field("coupon", req.Coupon))
|
||||
return nil, errors.Wrapf(err, "find coupon error: %v", err.Error())
|
||||
}
|
||||
if couponInfo.Count <= couponInfo.UsedCount {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.CouponInsufficientUsage), "coupon used")
|
||||
}
|
||||
coupon = calculateCoupon(amount, couponInfo)
|
||||
}
|
||||
payment, err := l.svcCtx.PaymentModel.FindOne(l.ctx, req.Payment)
|
||||
if err != nil {
|
||||
l.Error("[Renewal] Database query error", logger.Field("error", err.Error()), logger.Field("payment", req.Payment))
|
||||
return nil, errors.Wrapf(err, "find payment error: %v", err.Error())
|
||||
}
|
||||
amount -= coupon
|
||||
|
||||
var deductionAmount int64
|
||||
// Check user deduction amount
|
||||
if u.GiftAmount > 0 {
|
||||
if u.GiftAmount >= amount {
|
||||
deductionAmount = amount
|
||||
amount = 0
|
||||
u.GiftAmount -= amount
|
||||
} else {
|
||||
deductionAmount = u.GiftAmount
|
||||
amount -= u.GiftAmount
|
||||
u.GiftAmount = 0
|
||||
}
|
||||
}
|
||||
|
||||
var feeAmount int64
|
||||
// Calculate the handling fee
|
||||
if amount > 0 {
|
||||
feeAmount = calculateFee(amount, payment)
|
||||
}
|
||||
|
||||
amount += feeAmount
|
||||
|
||||
// create order
|
||||
orderInfo := order.Order{
|
||||
UserId: u.Id,
|
||||
ParentId: userSubscribe.OrderId,
|
||||
OrderNo: orderNo,
|
||||
Type: 2,
|
||||
Quantity: req.Quantity,
|
||||
Price: price,
|
||||
Amount: amount,
|
||||
GiftAmount: deductionAmount,
|
||||
Discount: discountAmount,
|
||||
Coupon: req.Coupon,
|
||||
CouponDiscount: coupon,
|
||||
PaymentId: payment.Id,
|
||||
Method: payment.Platform,
|
||||
FeeAmount: feeAmount,
|
||||
Status: 1,
|
||||
SubscribeId: userSubscribe.SubscribeId,
|
||||
SubscribeToken: userSubscribe.Token,
|
||||
}
|
||||
// Database transaction
|
||||
err = l.svcCtx.DB.Transaction(func(db *gorm.DB) error {
|
||||
// update user deduction && Pre deduction ,Return after canceling the order
|
||||
if orderInfo.GiftAmount > 0 {
|
||||
// update user deduction && Pre deduction ,Return after canceling the order
|
||||
if err := l.svcCtx.UserModel.Update(l.ctx, u, db); err != nil {
|
||||
l.Error("[Purchase] Database update error", logger.Field("error", err.Error()), logger.Field("user", u))
|
||||
return err
|
||||
}
|
||||
// create deduction record
|
||||
deductionLog := user.GiftAmountLog{
|
||||
UserId: orderInfo.UserId,
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
Amount: orderInfo.GiftAmount,
|
||||
Type: 2,
|
||||
Balance: u.GiftAmount,
|
||||
Remark: "Renewal order deduction",
|
||||
}
|
||||
if err := db.Model(&user.GiftAmountLog{}).Create(&deductionLog).Error; err != nil {
|
||||
l.Error("[Renewal] Database insert error", logger.Field("error", err.Error()), logger.Field("deductionLog", deductionLog))
|
||||
return err
|
||||
}
|
||||
}
|
||||
// insert order
|
||||
return db.Model(&order.Order{}).Create(&orderInfo).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Error("[Renewal] Database insert error", logger.Field("error", err.Error()), logger.Field("order", orderInfo))
|
||||
return nil, errors.Wrapf(err, "insert order error: %v", err.Error())
|
||||
}
|
||||
// Deferred task
|
||||
payload := queue.DeferCloseOrderPayload{
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
}
|
||||
val, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
l.Error("[Renewal] Marshal payload error", logger.Field("error", err.Error()), logger.Field("payload", payload))
|
||||
}
|
||||
task := asynq.NewTask(queue.DeferCloseOrder, val, asynq.MaxRetry(3))
|
||||
taskInfo, err := l.svcCtx.Queue.Enqueue(task, asynq.ProcessIn(CloseOrderTimeMinutes*time.Minute))
|
||||
if err != nil {
|
||||
l.Error("[Renewal] Enqueue task error", logger.Field("error", err.Error()), logger.Field("task", task))
|
||||
} else {
|
||||
l.Info("[Renewal] Enqueue task success", logger.Field("TaskID", taskInfo.ID))
|
||||
}
|
||||
return &types.RenewalOrderResponse{
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
queue "github.com/perfect-panel/server/queue/types"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type ResetTrafficLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Reset traffic
|
||||
func NewResetTrafficLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ResetTrafficLogic {
|
||||
return &ResetTrafficLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ResetTrafficLogic) ResetTraffic(req *types.ResetTrafficOrderRequest) (resp *types.ResetTrafficOrderResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
// find user subscription
|
||||
userSubscribe, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, req.UserSubscribeID)
|
||||
if err != nil {
|
||||
l.Error("[ResetTraffic] Database query error", logger.Field("error", err.Error()), logger.Field("UserSubscribeID", req.UserSubscribeID))
|
||||
return nil, errors.Wrapf(err, "find user subscribe error: %v", err.Error())
|
||||
}
|
||||
if userSubscribe.Subscribe == nil {
|
||||
l.Error("[ResetTraffic] subscribe not found", logger.Field("UserSubscribeID", req.UserSubscribeID))
|
||||
return nil, errors.New("subscribe not found")
|
||||
}
|
||||
amount := userSubscribe.Subscribe.Replacement
|
||||
var deductionAmount int64
|
||||
// Check user deduction amount
|
||||
if u.GiftAmount > 0 {
|
||||
if u.GiftAmount >= amount {
|
||||
deductionAmount = amount
|
||||
amount = 0
|
||||
u.GiftAmount -= amount
|
||||
} else {
|
||||
deductionAmount = u.GiftAmount
|
||||
amount -= u.GiftAmount
|
||||
u.GiftAmount = 0
|
||||
}
|
||||
}
|
||||
// find payment method
|
||||
payment, err := l.svcCtx.PaymentModel.FindOne(l.ctx, req.Payment)
|
||||
if err != nil {
|
||||
l.Error("[ResetTraffic] Database query error", logger.Field("error", err.Error()), logger.Field("payment", req.Payment))
|
||||
return nil, errors.Wrapf(err, "find payment error: %v", err.Error())
|
||||
}
|
||||
var feeAmount int64
|
||||
// Calculate the handling fee
|
||||
if amount > 0 {
|
||||
feeAmount = calculateFee(amount, payment)
|
||||
}
|
||||
// create order
|
||||
orderInfo := order.Order{
|
||||
Id: 0,
|
||||
ParentId: userSubscribe.OrderId,
|
||||
UserId: u.Id,
|
||||
OrderNo: tool.GenerateTradeNo(),
|
||||
Type: 3,
|
||||
Price: userSubscribe.Subscribe.Replacement,
|
||||
Amount: amount + feeAmount,
|
||||
GiftAmount: deductionAmount,
|
||||
FeeAmount: feeAmount,
|
||||
PaymentId: req.Payment,
|
||||
Method: payment.Platform,
|
||||
Status: 1,
|
||||
SubscribeId: userSubscribe.SubscribeId,
|
||||
SubscribeToken: userSubscribe.Token,
|
||||
}
|
||||
// Database transaction
|
||||
err = l.svcCtx.DB.Transaction(func(db *gorm.DB) error {
|
||||
// update user deduction && Pre deduction ,Return after canceling the order
|
||||
if orderInfo.GiftAmount > 0 {
|
||||
// update user deduction && Pre deduction ,Return after canceling the order
|
||||
if err := l.svcCtx.UserModel.Update(l.ctx, u, db); err != nil {
|
||||
l.Error("[ResetTraffic] Database update error", logger.Field("error", err.Error()), logger.Field("user", u))
|
||||
return err
|
||||
}
|
||||
// create deduction record
|
||||
deductionLog := user.GiftAmountLog{
|
||||
UserId: orderInfo.UserId,
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
Amount: orderInfo.GiftAmount,
|
||||
Type: 2,
|
||||
Balance: u.GiftAmount,
|
||||
Remark: "ResetTraffic order deduction",
|
||||
}
|
||||
if err := db.Model(&user.GiftAmountLog{}).Create(&deductionLog).Error; err != nil {
|
||||
l.Error("[ResetTraffic] Database insert error", logger.Field("error", err.Error()), logger.Field("deductionLog", deductionLog))
|
||||
return err
|
||||
}
|
||||
}
|
||||
// insert order
|
||||
return db.Model(&order.Order{}).Create(&orderInfo).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Error("[ResetTraffic] Database insert error", logger.Field("error", err.Error()), logger.Field("order", orderInfo))
|
||||
return nil, errors.Wrapf(err, "insert order error: %v", err.Error())
|
||||
}
|
||||
// Deferred task
|
||||
payload := queue.DeferCloseOrderPayload{
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
}
|
||||
val, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
l.Error("[ResetTraffic] Marshal payload error", logger.Field("error", err.Error()), logger.Field("payload", payload))
|
||||
}
|
||||
task := asynq.NewTask(queue.DeferCloseOrder, val, asynq.MaxRetry(3))
|
||||
taskInfo, err := l.svcCtx.Queue.Enqueue(task, asynq.ProcessIn(CloseOrderTimeMinutes*time.Minute))
|
||||
if err != nil {
|
||||
l.Error("[ResetTraffic] Enqueue task error", logger.Field("error", err.Error()), logger.Field("task", task))
|
||||
} else {
|
||||
l.Info("[ResetTraffic] Enqueue task success", logger.Field("TaskID", taskInfo.ID))
|
||||
}
|
||||
return &types.ResetTrafficOrderResponse{
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package payment
|
||||
|
||||
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/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GetAvailablePaymentMethodsLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewGetAvailablePaymentMethodsLogic Get available payment methods
|
||||
func NewGetAvailablePaymentMethodsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAvailablePaymentMethodsLogic {
|
||||
return &GetAvailablePaymentMethodsLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetAvailablePaymentMethodsLogic) GetAvailablePaymentMethods() (resp *types.GetAvailablePaymentMethodsResponse, err error) {
|
||||
data, err := l.svcCtx.PaymentModel.FindAvailableMethods(l.ctx)
|
||||
if err != nil {
|
||||
l.Error("[GetAvailablePaymentMethods] database error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "GetAvailablePaymentMethods: %v", err.Error())
|
||||
}
|
||||
resp = &types.GetAvailablePaymentMethodsResponse{
|
||||
List: make([]types.PaymentMethod, 0),
|
||||
}
|
||||
tool.DeepCopy(&resp.List, data)
|
||||
return
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type QueryApplicationConfigLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get application config
|
||||
func NewQueryApplicationConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryApplicationConfigLogic {
|
||||
return &QueryApplicationConfigLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryApplicationConfigLogic) QueryApplicationConfig() (resp *types.ApplicationResponse, err error) {
|
||||
resp = &types.ApplicationResponse{}
|
||||
var applications []*application.Application
|
||||
err = l.svcCtx.ApplicationModel.Transaction(l.ctx, func(tx *gorm.DB) (err error) {
|
||||
return tx.Model(applications).Preload("ApplicationVersions").Find(&applications).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[QueryApplicationConfig] get application error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get application error: %v", err.Error())
|
||||
}
|
||||
|
||||
if len(applications) == 0 {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
for _, app := range applications {
|
||||
applicationResponse := types.ApplicationResponseInfo{
|
||||
Id: app.Id,
|
||||
Name: app.Name,
|
||||
Icon: app.Icon,
|
||||
Description: app.Description,
|
||||
SubscribeType: app.SubscribeType,
|
||||
}
|
||||
applicationVersions := app.ApplicationVersions
|
||||
if len(applicationVersions) != 0 {
|
||||
for _, applicationVersion := range applicationVersions {
|
||||
/*if !applicationVersion.IsDefault {
|
||||
continue
|
||||
}*/
|
||||
switch applicationVersion.Platform {
|
||||
case "ios":
|
||||
applicationResponse.Platform.IOS = append(applicationResponse.Platform.IOS, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "macos":
|
||||
applicationResponse.Platform.MacOS = append(applicationResponse.Platform.MacOS, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "linux":
|
||||
applicationResponse.Platform.Linux = append(applicationResponse.Platform.Linux, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "android":
|
||||
applicationResponse.Platform.Android = append(applicationResponse.Platform.Android, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "windows":
|
||||
applicationResponse.Platform.Windows = append(applicationResponse.Platform.Windows, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "harmony":
|
||||
applicationResponse.Platform.Harmony = append(applicationResponse.Platform.Harmony, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
resp.Applications = append(resp.Applications, applicationResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/subscribe"
|
||||
"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 QuerySubscribeGroupListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get subscribe group list
|
||||
func NewQuerySubscribeGroupListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QuerySubscribeGroupListLogic {
|
||||
return &QuerySubscribeGroupListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QuerySubscribeGroupListLogic) QuerySubscribeGroupList() (resp *types.QuerySubscribeGroupListResponse, err error) {
|
||||
var list []*subscribe.Group
|
||||
var total int64
|
||||
err = l.svcCtx.DB.Model(&subscribe.Group{}).Count(&total).Find(&list).Error
|
||||
if err != nil {
|
||||
l.Logger.Error("[QuerySubscribeGroupListLogic] get subscribe group list failed: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get subscribe group list failed: %v", err.Error())
|
||||
}
|
||||
groupList := make([]types.SubscribeGroup, 0)
|
||||
tool.DeepCopy(&groupList, list)
|
||||
return &types.QuerySubscribeGroupListResponse{
|
||||
Total: total,
|
||||
List: groupList,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"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 QuerySubscribeListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get subscribe list
|
||||
func NewQuerySubscribeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QuerySubscribeListLogic {
|
||||
return &QuerySubscribeListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QuerySubscribeListLogic) QuerySubscribeList() (resp *types.QuerySubscribeListResponse, err error) {
|
||||
|
||||
data, err := l.svcCtx.SubscribeModel.QuerySubscribeList(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("[QuerySubscribeListLogic] Database Error", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "QuerySubscribeList error: %v", err.Error())
|
||||
}
|
||||
resp = &types.QuerySubscribeListResponse{
|
||||
List: make([]types.Subscribe, 0),
|
||||
Total: int64(len(data)),
|
||||
}
|
||||
for _, v := range data {
|
||||
var sub types.Subscribe
|
||||
tool.DeepCopy(&sub, v)
|
||||
if v.Discount != "" {
|
||||
if err = json.Unmarshal([]byte(v.Discount), &sub.Discount); err != nil {
|
||||
l.Errorw("[QuerySubscribeListLogic] json.Unmarshal Error", logger.Field("error", err.Error()), logger.Field("value", v.Discount))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json.Unmarshal error: %v", err.Error())
|
||||
}
|
||||
} else {
|
||||
sub.Discount = make([]types.SubscribeDiscount, 0)
|
||||
}
|
||||
resp.List = append(resp.List, sub)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type QueryUserAlreadySubscribeLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get Already subscribed to package
|
||||
func NewQueryUserAlreadySubscribeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryUserAlreadySubscribeLogic {
|
||||
return &QueryUserAlreadySubscribeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryUserAlreadySubscribeLogic) QueryUserAlreadySubscribe() (resp *types.QueryUserSubscribeResp, err error) {
|
||||
resp = &types.QueryUserSubscribeResp{
|
||||
Data: make([]types.UserSubscribeData, 0),
|
||||
}
|
||||
userInfo := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
var orderIds []int64
|
||||
var subscribes []user.Subscribe
|
||||
err = l.svcCtx.OrderModel.Transaction(context.Background(), func(tx *gorm.DB) error {
|
||||
if err := tx.Model(&order.Order{}).Where("user_id = ? AND status in ?", userInfo.Id, []int64{2, 5}).Select("id").Find(&orderIds).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if len(orderIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
return tx.Model(&user.Subscribe{}).Where("user_id = ? AND order_id in ?", userInfo.Id, orderIds).Order("created_at desc").Find(&subscribes).Error
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find order error: %v", err.Error())
|
||||
}
|
||||
if len(subscribes) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
userAlreadySubscribe := make(map[int64]int64)
|
||||
for _, subscribe := range subscribes {
|
||||
userAlreadySubscribe[subscribe.SubscribeId] = subscribe.Id
|
||||
}
|
||||
|
||||
for k, v := range userAlreadySubscribe {
|
||||
resp.Data = append(resp.Data, types.UserSubscribeData{
|
||||
SubscribeId: k,
|
||||
UserSubscribeId: v,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type QueryUserAvailableUserSubscribeLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get Available subscriptions for users
|
||||
func NewQueryUserAvailableUserSubscribeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryUserAvailableUserSubscribeLogic {
|
||||
return &QueryUserAvailableUserSubscribeLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryUserAvailableUserSubscribeLogic) QueryUserAvailableUserSubscribe(req *types.AppUserSubscribeRequest) (resp *types.AppUserSubscbribeResponse, err error) {
|
||||
resp = &types.AppUserSubscbribeResponse{List: make([]types.AppUserSubcbribe, 0)}
|
||||
userInfo := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
//查询用户订阅
|
||||
subscribeDetails, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, userInfo.Id, 1, 2)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get query user subscribe error: %v", err.Error())
|
||||
}
|
||||
|
||||
userSubscribeMap := make(map[int64]types.AppUserSubcbribe)
|
||||
for _, sd := range subscribeDetails {
|
||||
userSubscribeInfo := types.AppUserSubcbribe{
|
||||
Id: sd.Id,
|
||||
Name: sd.Subscribe.Name,
|
||||
Traffic: sd.Traffic,
|
||||
Upload: sd.Upload,
|
||||
Download: sd.Download,
|
||||
ExpireTime: sd.ExpireTime.Format(time.DateTime),
|
||||
StartTime: sd.StartTime.Format(time.DateTime),
|
||||
DeviceLimit: sd.Subscribe.DeviceLimit,
|
||||
}
|
||||
|
||||
//不需要查询节点
|
||||
if req.ContainsNodes == nil || !*req.ContainsNodes {
|
||||
resp.List = append(resp.List, userSubscribeInfo)
|
||||
continue
|
||||
}
|
||||
|
||||
//拿到所有订阅下的服务组id
|
||||
var ids []int64
|
||||
for _, idStr := range strings.Split(sd.Subscribe.ServerGroup, ",") {
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
//根据服务组id拿到所有节点
|
||||
servers, err := l.svcCtx.ServerModel.FindServerListByGroupIds(l.ctx, ids)
|
||||
if err != nil {
|
||||
l.Logger.Errorf("FindServerListByGroupIds error: %v", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
for _, server := range servers {
|
||||
userSubscribeInfo.List = append(userSubscribeInfo.List, types.AppUserSubscbribeNode{
|
||||
Id: server.Id,
|
||||
Uuid: sd.UUID,
|
||||
Traffic: sd.Traffic,
|
||||
Upload: sd.Upload,
|
||||
Download: sd.Download,
|
||||
RelayNode: server.RelayNode,
|
||||
RelayMode: server.RelayMode,
|
||||
Longitude: server.Longitude,
|
||||
Latitude: server.Latitude,
|
||||
Tags: strings.Split(server.Tags, ","),
|
||||
Config: server.Config,
|
||||
ServerAddr: server.ServerAddr,
|
||||
Protocol: server.Protocol,
|
||||
SpeedLimit: server.SpeedLimit,
|
||||
City: server.City,
|
||||
Country: server.Country,
|
||||
Name: server.Name,
|
||||
})
|
||||
}
|
||||
resp.List = append(resp.List, userSubscribeInfo)
|
||||
userSubscribeMap[userSubscribeInfo.Id] = userSubscribeInfo
|
||||
}
|
||||
|
||||
for _, userSubscribeInfo := range userSubscribeMap {
|
||||
resp.List = append(resp.List, userSubscribeInfo)
|
||||
}
|
||||
return resp, nil
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ResetUserSubscribePeriodLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewResetUserSubscribePeriodLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ResetUserSubscribePeriodLogic {
|
||||
return &ResetUserSubscribePeriodLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ResetUserSubscribePeriodLogic) ResetUserSubscribePeriod(req *types.UserSubscribeResetPeriodRequest) (resp *types.UserSubscribeResetPeriodResponse, err error) {
|
||||
resp = &types.UserSubscribeResetPeriodResponse{}
|
||||
userInfo := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
subscribe, err := l.svcCtx.UserModel.FindOneSubscribe(l.ctx, req.UserSubscribeId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find order error: %v", err.Error())
|
||||
}
|
||||
if userInfo.Id != subscribe.UserId {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SubscribeNotAvailable), "user not authorized,subscribe not available")
|
||||
}
|
||||
|
||||
if time.Now().After(subscribe.ExpireTime) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SubscribeExpired), "subscribe expired")
|
||||
}
|
||||
|
||||
if subscribe.Traffic < 1 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ExistAvailableTraffic), "Unlimited data plan.")
|
||||
}
|
||||
|
||||
if (subscribe.Download + subscribe.Upload + 10240) < subscribe.Traffic {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ExistAvailableTraffic), "There is still available traffic.")
|
||||
}
|
||||
|
||||
subscribe.ExpireTime = subscribe.ExpireTime.AddDate(0, -1, 0)
|
||||
err = l.svcCtx.UserModel.UpdateSubscribe(l.ctx, subscribe)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update subscribe error: %v", err.Error())
|
||||
}
|
||||
resp.Status = true
|
||||
return
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DeleteAccountLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Delete Account
|
||||
func NewDeleteAccountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteAccountLogic {
|
||||
return &DeleteAccountLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *DeleteAccountLogic) DeleteAccount(req *types.DeleteAccountRequest) error {
|
||||
userInfo, exists := l.ctx.Value(constant.CtxKeyUser).(user.User)
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
var account string
|
||||
for _, authMethod := range userInfo.AuthMethods {
|
||||
if authMethod.AuthType == req.Method {
|
||||
account = authMethod.AuthIdentifier
|
||||
break
|
||||
}
|
||||
}
|
||||
if account == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if req.Method == "email" {
|
||||
emailConfig := l.svcCtx.Config.Email
|
||||
|
||||
if !emailConfig.Enable {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.EmailNotEnabled), "Email function is not enabled yet")
|
||||
}
|
||||
|
||||
if emailConfig.EnableVerify {
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeCacheKey, constant.Security, account)
|
||||
value, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
l.Errorw("Redis Error", logger.Field("error", err.Error()), logger.Field("cacheKey", cacheKey))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
var payload common.CacheKeyPayload
|
||||
err = json.Unmarshal([]byte(value), &payload)
|
||||
if err != nil {
|
||||
l.Errorw("Unmarshal Error", logger.Field("error", err.Error()), logger.Field("value", value))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
if payload.Code != req.Code {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cacheKey := fmt.Sprintf("%s:%s:%s", config.AuthCodeTelephoneCacheKey, constant.Security, account)
|
||||
value, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
l.Errorw("Redis Error", logger.Field("error", err.Error()), logger.Field("cacheKey", cacheKey))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
if value == "" {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
|
||||
var payload common.CacheKeyPayload
|
||||
if err := json.Unmarshal([]byte(value), &payload); err != nil {
|
||||
l.Errorw("[SendSmsCode]: Unmarshal Error", logger.Field("error", err.Error()), logger.Field("value", value))
|
||||
}
|
||||
if payload.Code != req.Code {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "code error")
|
||||
}
|
||||
}
|
||||
err := l.svcCtx.UserModel.Delete(l.ctx, userInfo.Id)
|
||||
if err != nil {
|
||||
l.Errorw("update user password error", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update user password")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type GetUserOnlineTimeStatisticsLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get user online time total
|
||||
func NewGetUserOnlineTimeStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserOnlineTimeStatisticsLogic {
|
||||
return &GetUserOnlineTimeStatisticsLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetUserOnlineTimeStatisticsLogic) GetUserOnlineTimeStatistics() (resp *types.GetUserOnlineTimeStatisticsResponse, err error) {
|
||||
u := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
//获取历史最长在线时间
|
||||
var OnlineSeconds int64
|
||||
if err := l.svcCtx.DB.Model(user.DeviceOnlineRecord{}).Where("user_id = ?", u.Id).Select("online_seconds").Order("online_seconds desc").Limit(1).Scan(&OnlineSeconds).Error; err != nil {
|
||||
l.Logger.Error(err)
|
||||
}
|
||||
|
||||
//获取历史连续最长在线天数
|
||||
var DurationDays int64
|
||||
if err := l.svcCtx.DB.Model(user.DeviceOnlineRecord{}).Where("user_id = ?", u.Id).Select("duration_days").Order("duration_days desc").Limit(1).Scan(&DurationDays).Error; err != nil {
|
||||
l.Logger.Error(err)
|
||||
}
|
||||
|
||||
//获取近七天在线情况
|
||||
var userOnlineRecord []user.DeviceOnlineRecord
|
||||
if err := l.svcCtx.DB.Model(&userOnlineRecord).Where("user_id = ? and created_at >= ?", u.Id, time.Now().AddDate(0, 0, -7).Format(time.DateTime)).Order("created_at desc").Find(&userOnlineRecord).Error; err != nil {
|
||||
l.Logger.Error(err)
|
||||
}
|
||||
|
||||
//获取当前连续在线天数
|
||||
var currentContinuousDays int64
|
||||
if len(userOnlineRecord) > 0 {
|
||||
currentContinuousDays = userOnlineRecord[0].DurationDays
|
||||
} else {
|
||||
currentContinuousDays = 1
|
||||
}
|
||||
|
||||
var dates []string
|
||||
for i := 0; i < 7; i++ {
|
||||
date := time.Now().AddDate(0, 0, -i).Format(time.DateOnly)
|
||||
dates = append(dates, date)
|
||||
}
|
||||
|
||||
onlineDays := make(map[string]types.WeeklyStat)
|
||||
for _, record := range userOnlineRecord {
|
||||
//获取近七天在线情况
|
||||
onlineTime := record.OnlineTime.Format(time.DateOnly)
|
||||
if weeklyStat, ok := onlineDays[onlineTime]; ok {
|
||||
weeklyStat.Hours += float64(record.OnlineSeconds)
|
||||
onlineDays[onlineTime] = weeklyStat
|
||||
} else {
|
||||
onlineDays[onlineTime] = types.WeeklyStat{
|
||||
Hours: float64(record.OnlineSeconds),
|
||||
//根据日期获取周几
|
||||
DayName: record.OnlineTime.Weekday().String(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//补全不存在的日期
|
||||
for _, date := range dates {
|
||||
if _, ok := onlineDays[date]; !ok {
|
||||
onlineTime, _ := time.Parse(time.DateOnly, date)
|
||||
onlineDays[date] = types.WeeklyStat{
|
||||
DayName: onlineTime.Weekday().String(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var keys []string
|
||||
for key := range onlineDays {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
//排序
|
||||
sort.Strings(keys)
|
||||
|
||||
var weeklyStats []types.WeeklyStat
|
||||
for index, key := range keys {
|
||||
weeklyStat := onlineDays[key]
|
||||
weeklyStat.Day = index + 1
|
||||
weeklyStat.Hours = weeklyStat.Hours / float64(3600)
|
||||
weeklyStats = append(weeklyStats, weeklyStat)
|
||||
}
|
||||
|
||||
resp = &types.GetUserOnlineTimeStatisticsResponse{
|
||||
WeeklyStats: weeklyStats,
|
||||
ConnectionRecords: types.ConnectionRecords{
|
||||
CurrentContinuousDays: currentContinuousDays,
|
||||
HistoryContinuousDays: DurationDays,
|
||||
LongestSingleConnection: OnlineSeconds / 60,
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/traffic"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type GetUserSubscribeTrafficLogsLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get user subcribe traffic logs
|
||||
func NewGetUserSubscribeTrafficLogsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserSubscribeTrafficLogsLogic {
|
||||
return &GetUserSubscribeTrafficLogsLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetUserSubscribeTrafficLogsLogic) GetUserSubscribeTrafficLogs(req *types.GetUserSubscribeTrafficLogsRequest) (resp *types.GetUserSubscribeTrafficLogsResponse, err error) {
|
||||
resp = &types.GetUserSubscribeTrafficLogsResponse{}
|
||||
u := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
var traffics []traffic.TrafficLog
|
||||
err = l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
|
||||
return db.Model(traffic.TrafficLog{}).Where("user_id = ? and `timestamp` >= ? and `timestamp` < ?", u.Id, time.UnixMilli(req.StartTime), time.UnixMilli(req.EndTime)).Find(&traffics).Error
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Errorw("get user subscribe traffic logs failed", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), err.Error())
|
||||
}
|
||||
|
||||
//合并多条记录为以天为单位
|
||||
trafficMap := make(map[string]*traffic.TrafficLog)
|
||||
for _, traf := range traffics {
|
||||
key := traf.Timestamp.Format(time.DateOnly)
|
||||
existTraf := trafficMap[key]
|
||||
if existTraf == nil {
|
||||
trafficMap[key] = &traf
|
||||
} else {
|
||||
existTraf.Upload = existTraf.Download + traf.Upload
|
||||
existTraf.Download = existTraf.Download + traf.Download
|
||||
trafficMap[key] = existTraf
|
||||
}
|
||||
}
|
||||
|
||||
startTime := time.UnixMilli(req.StartTime)
|
||||
EndTime := time.UnixMilli(req.EndTime)
|
||||
res := make(map[string]traffic.TrafficLog)
|
||||
|
||||
// 循环遍历每一天
|
||||
for current := startTime; !current.After(EndTime); current = current.AddDate(0, 0, 1) {
|
||||
dateStr := current.Format(time.DateOnly) // 格式化为日期字符串
|
||||
if trafficMap[dateStr] == nil {
|
||||
res[dateStr] = traffic.TrafficLog{
|
||||
Timestamp: current,
|
||||
}
|
||||
} else {
|
||||
res[dateStr] = *trafficMap[dateStr]
|
||||
}
|
||||
resp.List = append(resp.List, types.TrafficLog{
|
||||
Id: res[dateStr].Id,
|
||||
ServerId: res[dateStr].ServerId,
|
||||
Upload: res[dateStr].Upload,
|
||||
Download: res[dateStr].Download,
|
||||
Timestamp: res[dateStr].Timestamp.UnixMilli(),
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type QueryUserAffiliateListLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Query User Affiliate List
|
||||
func NewQueryUserAffiliateListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryUserAffiliateListLogic {
|
||||
return &QueryUserAffiliateListLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryUserAffiliateListLogic) QueryUserAffiliateList(req *types.QueryUserAffiliateListRequest) (resp *types.QueryUserAffiliateListResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
var data []*user.User
|
||||
var total int64
|
||||
err = l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
|
||||
return db.Model(&user.User{}).Order("id desc").Where("referer_id = ?", u.Id).Count(&total).Limit(req.Size).Offset((req.Page - 1) * req.Size).Find(&data).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("Query User Affiliate List failed: %v", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "Query User Affiliate List failed: %v", err.Error())
|
||||
}
|
||||
|
||||
list := make([]types.UserAffiliate, 0)
|
||||
for _, item := range data {
|
||||
list = append(list, types.UserAffiliate{
|
||||
//Email: tool.MaskEmail(item.Email),
|
||||
Avatar: item.Avatar,
|
||||
RegisteredAt: item.CreatedAt.UnixMilli(),
|
||||
Enable: *item.Enable,
|
||||
})
|
||||
}
|
||||
return &types.QueryUserAffiliateListResponse{
|
||||
Total: total,
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type QueryUserInfoLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// query user info
|
||||
func NewQueryUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryUserInfoLogic {
|
||||
return &QueryUserInfoLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryUserInfoLogic) QueryUserInfo() (resp *types.UserInfoResponse, err error) {
|
||||
u := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
var devices []types.UserDevice
|
||||
if len(u.UserDevices) != 0 {
|
||||
for _, device := range u.UserDevices {
|
||||
devices = append(devices, types.UserDevice{
|
||||
Id: device.Id,
|
||||
Identifier: device.Identifier,
|
||||
Online: device.Online,
|
||||
})
|
||||
}
|
||||
}
|
||||
var authMeths []types.UserAuthMethod
|
||||
authMethods, err := l.svcCtx.UserModel.FindUserAuthMethods(l.ctx, u.Id)
|
||||
if err == nil && len(authMeths) != 0 {
|
||||
for _, as := range authMethods {
|
||||
authMeths = append(authMeths, types.UserAuthMethod{
|
||||
AuthType: as.AuthType,
|
||||
AuthIdentifier: as.AuthIdentifier,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resp = &types.UserInfoResponse{
|
||||
Id: u.Id,
|
||||
Balance: u.Balance,
|
||||
Avatar: u.Avatar,
|
||||
ReferCode: u.ReferCode,
|
||||
RefererId: u.RefererId,
|
||||
Devices: devices,
|
||||
AuthMethods: authMeths,
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type QueryUserAffiliateLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Query User Affiliate Count
|
||||
func NewQueryUserAffiliateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryUserAffiliateLogic {
|
||||
return &QueryUserAffiliateLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryUserAffiliateLogic) QueryUserAffiliate() (resp *types.QueryUserAffiliateCountResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
var sum int64
|
||||
var total int64
|
||||
err = l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
|
||||
return db.Model(&user.User{}).Where("referer_id = ?", u.Id).Count(&total).Find(&user.User{}).Error
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "Query User Affiliate failed: %v", err)
|
||||
}
|
||||
err = l.svcCtx.UserModel.Transaction(l.ctx, func(db *gorm.DB) error {
|
||||
return db.Model(&user.CommissionLog{}).
|
||||
Where("user_id = ?", u.Id).
|
||||
Select("COALESCE(SUM(amount), 0)").
|
||||
Scan(&sum).Error
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "Query User Affiliate failed: %v", err)
|
||||
}
|
||||
|
||||
return &types.QueryUserAffiliateCountResponse{
|
||||
Registers: total,
|
||||
TotalCommission: sum,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"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 UpdatePasswordLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Update Password
|
||||
func NewUpdatePasswordLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdatePasswordLogic {
|
||||
return &UpdatePasswordLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UpdatePasswordLogic) UpdatePassword(req *types.UpdatePasswordRequeset) error {
|
||||
userInfo := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
|
||||
// Verify password
|
||||
if !tool.VerifyPassWord(req.Password, userInfo.Password) {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.UserPasswordError), "user password")
|
||||
}
|
||||
userInfo.Password = tool.EncodePassWord(req.NewPassword)
|
||||
err := l.svcCtx.UserModel.Update(l.ctx, userInfo)
|
||||
if err != nil {
|
||||
l.Errorw("update user password error", logger.Field("error", err.Error()))
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update user password")
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package ws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type AppWsLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// App heartbeat
|
||||
func NewAppWsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AppWsLogic {
|
||||
return &AppWsLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AppWsLogic) AppWs(w http.ResponseWriter, r *http.Request, userid, identifier string) error {
|
||||
//获取设备号
|
||||
if identifier == "" {
|
||||
return xerr.NewErrCode(xerr.DeviceNotExist)
|
||||
}
|
||||
//获取用户id
|
||||
userID, err := strconv.ParseInt(userid, 10, 64)
|
||||
if err != nil {
|
||||
return xerr.NewErrCode(xerr.UseridNotMatch)
|
||||
}
|
||||
|
||||
////获取session
|
||||
value := l.ctx.Value(constant.CtxKeySessionID)
|
||||
if value == nil {
|
||||
return xerr.NewErrCode(xerr.ErrorTokenInvalid)
|
||||
}
|
||||
session := value.(string)
|
||||
|
||||
//获取用户
|
||||
userInfo := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
|
||||
if userID != userInfo.Id {
|
||||
return xerr.NewErrCode(xerr.UseridNotMatch)
|
||||
}
|
||||
|
||||
_, err = l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, identifier)
|
||||
if err != nil {
|
||||
return xerr.NewErrCode(xerr.DeviceNotExist)
|
||||
}
|
||||
|
||||
//if device.UserId != userInfo.Id {
|
||||
// return xerr.NewErrCode(xerr.DeviceNotExist)
|
||||
//}
|
||||
|
||||
//默认在线设备1
|
||||
maxDevice := 0
|
||||
subscribe, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, userInfo.Id)
|
||||
if err == nil {
|
||||
for _, sub := range subscribe {
|
||||
if time.Now().Before(sub.ExpireTime) {
|
||||
deviceLimit := int(sub.Subscribe.DeviceLimit)
|
||||
if deviceLimit > maxDevice {
|
||||
maxDevice = deviceLimit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
l.svcCtx.DeviceManager.AddDevice(w, r, session, userID, identifier, maxDevice)
|
||||
return nil
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type GetApplicationLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get Tos Content
|
||||
func NewGetApplicationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetApplicationLogic {
|
||||
return &GetApplicationLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetApplicationLogic) GetApplication() (resp *types.GetAppcationResponse, err error) {
|
||||
resp = &types.GetAppcationResponse{}
|
||||
|
||||
cfg, err := l.svcCtx.ApplicationModel.FindOneConfig(l.ctx, 1)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
l.Logger.Error("[GetAppInfo] FindOneAppConfig error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "GetAppInfo FindOneAppConfig error: %v", err.Error())
|
||||
}
|
||||
if err != nil {
|
||||
resp.Config = types.ApplicationConfig{}
|
||||
} else {
|
||||
resp.Config = types.ApplicationConfig{
|
||||
AppId: cfg.AppId,
|
||||
EncryptionKey: cfg.EncryptionKey,
|
||||
EncryptionMethod: cfg.EncryptionMethod,
|
||||
Domains: strings.Split(cfg.Domains, ";"),
|
||||
StartupPicture: cfg.StartupPicture,
|
||||
StartupPictureSkipTime: cfg.StartupPictureSkipTime,
|
||||
}
|
||||
}
|
||||
|
||||
var applications []*application.Application
|
||||
err = l.svcCtx.ApplicationModel.Transaction(l.ctx, func(tx *gorm.DB) (err error) {
|
||||
return tx.Model(applications).Preload("ApplicationVersions").Find(&applications).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[QueryApplicationConfig] get application error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get application error: %v", err.Error())
|
||||
}
|
||||
|
||||
if len(applications) == 0 {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
for _, app := range applications {
|
||||
applicationResponse := types.ApplicationResponseInfo{
|
||||
Id: app.Id,
|
||||
Name: app.Name,
|
||||
Icon: app.Icon,
|
||||
Description: app.Description,
|
||||
SubscribeType: app.SubscribeType,
|
||||
}
|
||||
applicationVersions := app.ApplicationVersions
|
||||
if len(applicationVersions) != 0 {
|
||||
for _, applicationVersion := range applicationVersions {
|
||||
/*if !applicationVersion.IsDefault {
|
||||
continue
|
||||
}*/
|
||||
switch applicationVersion.Platform {
|
||||
case "ios":
|
||||
applicationResponse.Platform.IOS = append(applicationResponse.Platform.IOS, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "macos":
|
||||
applicationResponse.Platform.MacOS = append(applicationResponse.Platform.MacOS, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "linux":
|
||||
applicationResponse.Platform.Linux = append(applicationResponse.Platform.Linux, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "android":
|
||||
applicationResponse.Platform.Android = append(applicationResponse.Platform.Android, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "windows":
|
||||
applicationResponse.Platform.Windows = append(applicationResponse.Platform.Windows, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "harmony":
|
||||
applicationResponse.Platform.Harmony = append(applicationResponse.Platform.Harmony, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
resp.Applications = append(resp.Applications, applicationResponse)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type QueryApplicationConfigLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get application config
|
||||
func NewQueryApplicationConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryApplicationConfigLogic {
|
||||
return &QueryApplicationConfigLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryApplicationConfigLogic) QueryApplicationConfig() (resp *types.ApplicationResponse, err error) {
|
||||
resp = &types.ApplicationResponse{}
|
||||
var applications []*application.Application
|
||||
err = l.svcCtx.ApplicationModel.Transaction(l.ctx, func(tx *gorm.DB) (err error) {
|
||||
return tx.Model(applications).Preload("ApplicationVersions").Find(&applications).Error
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("[QueryApplicationConfig] get application error: ", logger.Field("error", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get application error: %v", err.Error())
|
||||
}
|
||||
|
||||
if len(applications) == 0 {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
for _, app := range applications {
|
||||
applicationResponse := types.ApplicationResponseInfo{
|
||||
Id: app.Id,
|
||||
Name: app.Name,
|
||||
Icon: app.Icon,
|
||||
Description: app.Description,
|
||||
SubscribeType: app.SubscribeType,
|
||||
}
|
||||
applicationVersions := app.ApplicationVersions
|
||||
if len(applicationVersions) != 0 {
|
||||
for _, applicationVersion := range applicationVersions {
|
||||
/*if !applicationVersion.IsDefault {
|
||||
continue
|
||||
}*/
|
||||
switch applicationVersion.Platform {
|
||||
case "ios":
|
||||
applicationResponse.Platform.IOS = append(applicationResponse.Platform.IOS, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "macos":
|
||||
applicationResponse.Platform.MacOS = append(applicationResponse.Platform.MacOS, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "linux":
|
||||
applicationResponse.Platform.Linux = append(applicationResponse.Platform.Linux, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "android":
|
||||
applicationResponse.Platform.Android = append(applicationResponse.Platform.Android, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "windows":
|
||||
applicationResponse.Platform.Windows = append(applicationResponse.Platform.Windows, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
case "harmony":
|
||||
applicationResponse.Platform.Harmony = append(applicationResponse.Platform.Harmony, &types.ApplicationVersion{
|
||||
Id: applicationVersion.Id,
|
||||
Url: applicationVersion.Url,
|
||||
Version: applicationVersion.Version,
|
||||
IsDefault: applicationVersion.IsDefault,
|
||||
Description: applicationVersion.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
resp.Applications = append(resp.Applications, applicationResponse)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/result"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
pkgaes "github.com/perfect-panel/server/pkg/aes"
|
||||
)
|
||||
|
||||
const (
|
||||
noWritten = -1
|
||||
defaultStatus = http.StatusOK
|
||||
key = "123456"
|
||||
)
|
||||
|
||||
func AppMiddleware(svc *svc.ServiceContext) func(c *gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
if !strings.Contains(c.Request.URL.Path, "/v1/app") {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
rw := NewResponseWriter(c, svc)
|
||||
if !rw.Decrypt() {
|
||||
result.HttpResult(c, nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidCiphertext), "Invalid ciphertext"))
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Writer = rw
|
||||
c.Next()
|
||||
rw.FlushAbort()
|
||||
}
|
||||
}
|
||||
|
||||
func NewResponseWriter(c *gin.Context, srvCtx *svc.ServiceContext) (rw *ResponseWriter) {
|
||||
rw = &ResponseWriter{
|
||||
c: c,
|
||||
body: new(bytes.Buffer),
|
||||
ResponseWriter: c.Writer,
|
||||
}
|
||||
applicationConfig, err := srvCtx.ApplicationModel.FindOneConfig(c, 1)
|
||||
if err != nil {
|
||||
logger.Errorf("[AppMiddleware] find application config error: %v", err.Error())
|
||||
return
|
||||
}
|
||||
if strings.ToUpper(applicationConfig.EncryptionMethod) == "AES" && applicationConfig.EncryptionKey != "" {
|
||||
rw.encryptionKey = applicationConfig.EncryptionKey
|
||||
rw.encryptionMethod = applicationConfig.EncryptionMethod
|
||||
rw.encryption = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Encrypt() {
|
||||
if !rw.encryption {
|
||||
return
|
||||
}
|
||||
buf := rw.body.Bytes()
|
||||
params := map[string]interface{}{}
|
||||
err := json.Unmarshal(buf, ¶ms)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
data := params["data"]
|
||||
if data != nil {
|
||||
var jsonData []byte
|
||||
str, ok := data.(string)
|
||||
if ok {
|
||||
jsonData = []byte(str)
|
||||
} else {
|
||||
jsonData, _ = json.Marshal(data)
|
||||
}
|
||||
encrypt, iv, err := pkgaes.Encrypt(jsonData, rw.encryptionKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
params["data"] = map[string]interface{}{
|
||||
"data": encrypt,
|
||||
"time": iv,
|
||||
}
|
||||
|
||||
}
|
||||
marshal, _ := json.Marshal(params)
|
||||
rw.body.Reset()
|
||||
rw.body.Write(marshal)
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Decrypt() bool {
|
||||
if !rw.encryption {
|
||||
return true
|
||||
}
|
||||
|
||||
//判断url链接中是否存在data和iv数据,存在就进行解密并设置回去
|
||||
query := rw.c.Request.URL.Query()
|
||||
dataStr := query.Get("data")
|
||||
timeStr := query.Get("time")
|
||||
if dataStr != "" && timeStr != "" {
|
||||
decrypt, err := pkgaes.Decrypt(dataStr, rw.encryptionKey, timeStr)
|
||||
if err == nil {
|
||||
params := map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(decrypt), ¶ms)
|
||||
if err == nil {
|
||||
for k, v := range params {
|
||||
query.Set(k, fmt.Sprintf("%v", v))
|
||||
}
|
||||
query.Del("data")
|
||||
query.Del("time")
|
||||
rw.c.Request.RequestURI = fmt.Sprintf("%s?%s", rw.c.Request.RequestURI[:strings.Index(rw.c.Request.RequestURI, "?")], query.Encode())
|
||||
rw.c.Request.URL.RawQuery = query.Encode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//判断body是否存在数据,存在就尝试解密,并设置回去
|
||||
body, err := io.ReadAll(rw.c.Request.Body)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(body) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
params := map[string]interface{}{}
|
||||
err = json.Unmarshal(body, ¶ms)
|
||||
data := params["data"]
|
||||
nonce := params["time"]
|
||||
if err != nil || data == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
str, ok := data.(string)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
iv, ok := nonce.(string)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
decrypt, err := pkgaes.Decrypt(str, rw.encryptionKey, iv)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
rw.c.Request.Body = io.NopCloser(bytes.NewBuffer([]byte(decrypt)))
|
||||
return true
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) FlushAbort() {
|
||||
defer rw.c.Abort()
|
||||
responseBody := rw.body.String()
|
||||
fmt.Println("Original Response Body:", responseBody)
|
||||
rw.flush = true
|
||||
if rw.encryption {
|
||||
rw.Encrypt()
|
||||
}
|
||||
_, err := rw.Write(rw.body.Bytes())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type ResponseWriter struct {
|
||||
http.ResponseWriter
|
||||
size int
|
||||
status int
|
||||
flush bool
|
||||
body *bytes.Buffer
|
||||
c *gin.Context
|
||||
encryption bool
|
||||
encryptionKey string
|
||||
encryptionMethod string
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Unwrap() http.ResponseWriter {
|
||||
return rw.ResponseWriter
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (rw *ResponseWriter) reset(writer http.ResponseWriter) {
|
||||
rw.ResponseWriter = writer
|
||||
rw.size = noWritten
|
||||
rw.status = defaultStatus
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) WriteHeader(code int) {
|
||||
if code > 0 && rw.status != code {
|
||||
if rw.Written() {
|
||||
return
|
||||
}
|
||||
rw.status = code
|
||||
}
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) WriteHeaderNow() {
|
||||
if !rw.Written() {
|
||||
rw.size = 0
|
||||
rw.ResponseWriter.WriteHeader(rw.status)
|
||||
}
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Write(data []byte) (n int, err error) {
|
||||
if rw.flush {
|
||||
rw.WriteHeaderNow()
|
||||
n, err = rw.ResponseWriter.Write(data)
|
||||
rw.size += n
|
||||
} else {
|
||||
rw.body.Write(data)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) WriteString(s string) (n int, err error) {
|
||||
if rw.flush {
|
||||
rw.WriteHeaderNow()
|
||||
n, err = rw.ResponseWriter.Write([]byte(s))
|
||||
rw.size += n
|
||||
} else {
|
||||
rw.body.Write([]byte(s))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Status() int {
|
||||
return rw.status
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Size() int {
|
||||
return rw.size
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Written() bool {
|
||||
return rw.size != noWritten
|
||||
}
|
||||
|
||||
// Hijack implements the http.Hijacker interface.
|
||||
func (rw *ResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
if rw.size < 0 {
|
||||
rw.size = 0
|
||||
}
|
||||
return rw.ResponseWriter.(http.Hijacker).Hijack()
|
||||
}
|
||||
|
||||
// CloseNotify implements the http.CloseNotifier interface.
|
||||
func (rw *ResponseWriter) CloseNotify() <-chan bool {
|
||||
// 通过 r.Context().Done() 来监听请求的取消
|
||||
done := rw.c.Request.Context().Done()
|
||||
closed := make(chan bool)
|
||||
|
||||
// 当上下文被取消时,通过 closed channel 发送通知
|
||||
go func() {
|
||||
<-done
|
||||
closed <- true
|
||||
}()
|
||||
|
||||
return closed
|
||||
}
|
||||
|
||||
// Flush implements the http.Flusher interface.
|
||||
func (rw *ResponseWriter) Flush() {
|
||||
rw.WriteHeaderNow()
|
||||
rw.ResponseWriter.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Pusher() (pusher http.Pusher) {
|
||||
if pusher, ok := rw.ResponseWriter.(http.Pusher); ok {
|
||||
return pusher
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Application struct {
|
||||
Id int64 `gorm:"primary_key"`
|
||||
Name string `gorm:"type:varchar(255);default:'';not null;comment:应用名称"`
|
||||
Icon string `gorm:"type:text;not null;comment:应用图标"`
|
||||
Description string `gorm:"type:text;comment:更新描述"`
|
||||
SubscribeType string `gorm:"type:varchar(50);default:'';not null;comment:订阅类型"`
|
||||
ApplicationVersions []ApplicationVersion
|
||||
CreatedAt time.Time `gorm:"<-:create;comment:创建时间"`
|
||||
UpdatedAt time.Time `gorm:"comment:更新时间"`
|
||||
}
|
||||
|
||||
func (Application) TableName() string {
|
||||
return "application"
|
||||
}
|
||||
|
||||
type ApplicationVersion struct {
|
||||
Id int64 `gorm:"primary_key"`
|
||||
Url string `gorm:"type:varchar(255);default:'';not null;comment:应用地址"`
|
||||
Version string `gorm:"type:varchar(255);default:'';not null;comment:应用版本"`
|
||||
Platform string `gorm:"type:varchar(50);default:'';not null;comment:应用平台"`
|
||||
IsDefault bool `gorm:"type:tinyint(1);not null;default:0;comment:默认版本"`
|
||||
Description string `gorm:"type:text;comment:更新描述"`
|
||||
ApplicationId int64 `gorm:"comment:所属应用"`
|
||||
CreatedAt time.Time `gorm:"<-:create;comment:创建时间"`
|
||||
UpdatedAt time.Time `gorm:"comment:更新时间"`
|
||||
}
|
||||
|
||||
func (ApplicationVersion) TableName() string {
|
||||
return "application_version"
|
||||
}
|
||||
|
||||
type ApplicationConfig struct {
|
||||
Id int64 `gorm:"primary_key"`
|
||||
AppId int64 `gorm:"type:int;not null;default:0;comment:App id"`
|
||||
EncryptionKey string `gorm:"type:text;comment:Encryption Key"`
|
||||
EncryptionMethod string `gorm:"type:varchar(255);comment:Encryption Method"`
|
||||
Domains string `gorm:"type:text;comment:Domains"`
|
||||
StartupPicture string `gorm:"type:text;comment:Startup Picture"`
|
||||
StartupPictureSkipTime int64 `gorm:"type:int;not null;default:0;comment:Startup Picture Skip Time"`
|
||||
InvitationLink string `gorm:"type:text;comment:Invitation Link"`
|
||||
KrWebsiteId string `gorm:"type:varchar(255);default:'';comment:Kr Website ID"`
|
||||
CreatedAt time.Time `gorm:"<-:create;comment:Create Time"`
|
||||
UpdatedAt time.Time `gorm:"comment:Update Time"`
|
||||
}
|
||||
|
||||
func (ApplicationConfig) TableName() string {
|
||||
return "application_config"
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/pkg/cache"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var _ Model = (*customApplicationModel)(nil)
|
||||
var (
|
||||
cacheApplicationIdPrefix = "cache:application:id:"
|
||||
cacheApplicationConfigIdPrefix = "cache:application:config:id:"
|
||||
cacheApplicationVersionIdPrefix = "cache:application:version:id:"
|
||||
)
|
||||
|
||||
type (
|
||||
Model interface {
|
||||
applicationModel
|
||||
customApplicationLogicModel
|
||||
}
|
||||
applicationModel interface {
|
||||
Insert(ctx context.Context, data *Application) error
|
||||
FindOne(ctx context.Context, id int64) (*Application, error)
|
||||
Update(ctx context.Context, data *Application) error
|
||||
Delete(ctx context.Context, id int64) error
|
||||
InsertVersion(ctx context.Context, data *ApplicationVersion) error
|
||||
FindOneVersion(ctx context.Context, id int64) (*ApplicationVersion, error)
|
||||
UpdateVersion(ctx context.Context, data *ApplicationVersion) error
|
||||
InsertConfig(ctx context.Context, data *ApplicationConfig) error
|
||||
FindOneConfig(ctx context.Context, id int64) (*ApplicationConfig, error)
|
||||
UpdateConfig(ctx context.Context, data *ApplicationConfig) error
|
||||
DeleteVersion(ctx context.Context, id int64) error
|
||||
Transaction(ctx context.Context, fn func(db *gorm.DB) error) error
|
||||
}
|
||||
|
||||
customApplicationModel struct {
|
||||
*defaultApplicationModel
|
||||
}
|
||||
defaultApplicationModel struct {
|
||||
cache.CachedConn
|
||||
table string
|
||||
}
|
||||
)
|
||||
|
||||
func newApplicationModel(db *gorm.DB, c *redis.Client) *defaultApplicationModel {
|
||||
return &defaultApplicationModel{
|
||||
CachedConn: cache.NewConn(db, c),
|
||||
table: "`Application`",
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) getCacheKeys(data *Application) []string {
|
||||
if data == nil {
|
||||
return []string{}
|
||||
}
|
||||
ApplicationIdKey := fmt.Sprintf("%s%v", cacheApplicationIdPrefix, data.Id)
|
||||
cacheKeys := []string{
|
||||
ApplicationIdKey,
|
||||
config.ApplicationKey,
|
||||
}
|
||||
return cacheKeys
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) Insert(ctx context.Context, data *Application) error {
|
||||
err := m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
return conn.Create(&data).Error
|
||||
}, m.getCacheKeys(data)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) FindOne(ctx context.Context, id int64) (*Application, error) {
|
||||
ApplicationIdKey := fmt.Sprintf("%s%v", cacheApplicationIdPrefix, id)
|
||||
var resp Application
|
||||
err := m.QueryCtx(ctx, &resp, ApplicationIdKey, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Model(&Application{}).Preload("ApplicationVersions").Where("`id` = ?", id).First(&resp).Error
|
||||
})
|
||||
switch {
|
||||
case err == nil:
|
||||
return &resp, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) Update(ctx context.Context, data *Application) error {
|
||||
old, err := m.FindOne(ctx, data.Id)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
return db.Save(data).Error
|
||||
}, m.getCacheKeys(old)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) Delete(ctx context.Context, id int64) error {
|
||||
data, err := m.FindOne(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
err = db.Where("application_id = ?", id).Delete(&ApplicationVersion{}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return db.Delete(&Application{}, id).Error
|
||||
}, m.getCacheKeys(data)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) getVersionCacheKeys(data *ApplicationVersion) []string {
|
||||
if data == nil {
|
||||
return []string{}
|
||||
}
|
||||
ApplicationVersionIdKey := fmt.Sprintf("%s%v", cacheApplicationVersionIdPrefix, data.Id)
|
||||
cacheKeys := []string{
|
||||
ApplicationVersionIdKey,
|
||||
config.ApplicationKey,
|
||||
}
|
||||
return cacheKeys
|
||||
}
|
||||
func (m *defaultApplicationModel) getConfigCacheKeys(data *ApplicationConfig) []string {
|
||||
if data == nil {
|
||||
return []string{}
|
||||
}
|
||||
ApplicationConfigIdKey := fmt.Sprintf("%s%v", cacheApplicationConfigIdPrefix, data.Id)
|
||||
cacheKeys := []string{
|
||||
ApplicationConfigIdKey,
|
||||
config.ApplicationKey,
|
||||
}
|
||||
return cacheKeys
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) InsertVersion(ctx context.Context, data *ApplicationVersion) error {
|
||||
err := m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
return conn.Transaction(func(tx *gorm.DB) error {
|
||||
if data.IsDefault {
|
||||
err := tx.Model(&ApplicationVersion{}).
|
||||
Where("application_id = ? and platform = ? and default_version = ?", data.ApplicationId, data.Platform, data.IsDefault).
|
||||
Updates(map[string]interface{}{"default_version": false}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return tx.Create(&data).Error
|
||||
})
|
||||
}, m.getVersionCacheKeys(data)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) FindOneVersion(ctx context.Context, id int64) (*ApplicationVersion, error) {
|
||||
ApplicationVersionIdKey := fmt.Sprintf("%s%v", cacheApplicationVersionIdPrefix, id)
|
||||
var resp ApplicationVersion
|
||||
err := m.QueryCtx(ctx, &resp, ApplicationVersionIdKey, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Model(&ApplicationVersion{}).Where("`id` = ?", id).First(&resp).Error
|
||||
})
|
||||
switch {
|
||||
case err == nil:
|
||||
return &resp, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) UpdateVersion(ctx context.Context, data *ApplicationVersion) error {
|
||||
old, err := m.FindOneVersion(ctx, data.Id)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
return conn.Transaction(func(tx *gorm.DB) error {
|
||||
if data.IsDefault {
|
||||
err := tx.Model(&ApplicationVersion{}).
|
||||
Where("application_id = ? and platform = ? and default_version = ?", data.ApplicationId, data.Platform, data.IsDefault).
|
||||
Updates(map[string]interface{}{"default_version": false}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return tx.Save(data).Error
|
||||
})
|
||||
}, m.getVersionCacheKeys(old)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) InsertConfig(ctx context.Context, data *ApplicationConfig) error {
|
||||
err := m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
return conn.Create(&data).Error
|
||||
}, m.getConfigCacheKeys(data)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) FindOneConfig(ctx context.Context, id int64) (*ApplicationConfig, error) {
|
||||
ApplicationConfigIdKey := fmt.Sprintf("%s%v", cacheApplicationConfigIdPrefix, id)
|
||||
var resp ApplicationConfig
|
||||
err := m.QueryCtx(ctx, &resp, ApplicationConfigIdKey, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Model(&ApplicationConfig{}).Where("`id` = ?", id).First(&resp).Error
|
||||
})
|
||||
switch {
|
||||
case err == nil:
|
||||
return &resp, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) UpdateConfig(ctx context.Context, data *ApplicationConfig) error {
|
||||
old, err := m.FindOneConfig(ctx, data.Id)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
return conn.Save(data).Error
|
||||
}, m.getConfigCacheKeys(old)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) DeleteVersion(ctx context.Context, id int64) error {
|
||||
data, err := m.FindOneVersion(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
return db.Delete(&ApplicationVersion{}, id).Error
|
||||
}, m.getVersionCacheKeys(data)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultApplicationModel) Transaction(ctx context.Context, fn func(db *gorm.DB) error) error {
|
||||
return m.TransactCtx(ctx, fn)
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type customApplicationLogicModel interface {
|
||||
}
|
||||
|
||||
// NewModel returns a model for the database table.
|
||||
func NewModel(conn *gorm.DB, c *redis.Client) Model {
|
||||
return &customApplicationModel{
|
||||
defaultApplicationModel: newApplicationModel(conn, c),
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,8 @@ import (
|
||||
"github.com/perfect-panel/server/internal/model/ads"
|
||||
"github.com/perfect-panel/server/internal/model/cache"
|
||||
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/model/announcement"
|
||||
"github.com/perfect-panel/server/internal/model/application"
|
||||
"github.com/perfect-panel/server/internal/model/auth"
|
||||
"github.com/perfect-panel/server/internal/model/coupon"
|
||||
"github.com/perfect-panel/server/internal/model/document"
|
||||
@@ -30,6 +27,9 @@ import (
|
||||
"github.com/perfect-panel/server/pkg/limit"
|
||||
"github.com/perfect-panel/server/pkg/nodeMultiplier"
|
||||
"github.com/perfect-panel/server/pkg/orm"
|
||||
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -54,7 +54,6 @@ type ServiceContext struct {
|
||||
DocumentModel document.Model
|
||||
SubscribeModel subscribe.Model
|
||||
TrafficLogModel traffic.Model
|
||||
ApplicationModel application.Model
|
||||
AnnouncementModel announcement.Model
|
||||
SubscribeTypeModel subscribeType.Model
|
||||
|
||||
@@ -106,7 +105,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
DocumentModel: document.NewModel(db, rds),
|
||||
SubscribeModel: subscribe.NewModel(db, rds),
|
||||
TrafficLogModel: traffic.NewModel(db),
|
||||
ApplicationModel: application.NewModel(db, rds),
|
||||
AnnouncementModel: announcement.NewModel(db, rds),
|
||||
}
|
||||
srv.DeviceManager = NewDeviceManager(srv)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user