refactor(api): remove deprecated application-related endpoints and types

This commit is contained in:
Chang lue Tsen 2025-08-17 12:14:55 -04:00
parent 14a86c50b2
commit 8996a62b54
118 changed files with 6 additions and 7156 deletions

View File

@ -11,50 +11,6 @@ info (
import "../types.api" import "../types.api"
type ( type (
// Update application request
UpdateApplicationRequest {
Id int64 `json:"id" validate:"required"`
Icon string `json:"icon"`
Name string `json:"name"`
Description string `json:"description"`
SubscribeType string `json:"subscribe_type"`
Platform ApplicationPlatform `json:"platform"`
}
// Create application request
CreateApplicationRequest {
Icon string `json:"icon"`
Name string `json:"name"`
Description string `json:"description"`
SubscribeType string `json:"subscribe_type"`
Platform ApplicationPlatform `json:"platform"`
}
// Update application request
UpdateApplicationVersionRequest {
Id int64 `json:"id" validate:"required"`
Url string `json:"url"`
Version string `json:"version" validate:"required"`
Description string `json:"description"`
Platform string `json:"platform" validate:"required,oneof=windows mac linux android ios harmony"`
IsDefault bool `json:"is_default"`
ApplicationId int64 `json:"application_id" validate:"required"`
}
// Create application request
CreateApplicationVersionRequest {
Url string `json:"url"`
Version string `json:"version" validate:"required"`
Description string `json:"description"`
Platform string `json:"platform" validate:"required,oneof=windows mac linux android ios harmony"`
IsDefault bool `json:"is_default"`
ApplicationId int64 `json:"application_id" validate:"required"`
}
// Delete application request
DeleteApplicationRequest {
Id int64 `json:"id" validate:"required"`
}
// Delete application request
DeleteApplicationVersionRequest {
Id int64 `json:"id" validate:"required"`
}
GetNodeMultiplierResponse { GetNodeMultiplierResponse {
Periods []TimePeriod `json:"periods"` Periods []TimePeriod `json:"periods"`
} }
@ -90,42 +46,6 @@ service ppanel {
@handler GetSubscribeType @handler GetSubscribeType
get /subscribe_type returns (SubscribeType) get /subscribe_type returns (SubscribeType)
@doc "update application config"
@handler UpdateApplicationConfig
put /application_config (ApplicationConfig)
@doc "get application config"
@handler GetApplicationConfig
get /application_config returns (ApplicationConfig)
@doc "Get application"
@handler GetApplication
get /application returns (ApplicationResponse)
@doc "Update application"
@handler UpdateApplication
put /application (UpdateApplicationRequest)
@doc "Create application"
@handler CreateApplication
post /application (CreateApplicationRequest)
@doc "Delete application"
@handler DeleteApplication
delete /application (DeleteApplicationRequest)
@doc "Update application version"
@handler UpdateApplicationVersion
put /application_version (UpdateApplicationVersionRequest)
@doc "Create application version"
@handler CreateApplicationVersion
post /application_version (CreateApplicationVersionRequest)
@doc "Delete application"
@handler DeleteApplicationVersion
delete /application_version (DeleteApplicationVersionRequest)
@doc "Get register config" @doc "Get register config"
@handler GetRegisterConfig @handler GetRegisterConfig
get /register_config returns (RegisterConfig) get /register_config returns (RegisterConfig)

View File

@ -1,23 +0,0 @@
syntax = "v1"
info (
title: "Announcement API"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import "../types.api"
@server (
prefix: v1/app/announcement
group: app/announcement
middleware: AppMiddleware,AuthMiddleware
)
service ppanel {
@doc "Query announcement"
@handler QueryAnnouncement
get /list (QueryAnnouncementRequest) returns (QueryAnnouncementResponse)
}

View File

@ -1,104 +0,0 @@
syntax = "v1"
info (
title: "App Auth Api"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import (
"../types.api"
)
type (
AppAuthCheckRequest {
Method string `json:"method" validate:"required" validate:"required,oneof=device email mobile"`
Account string `json:"account"`
Identifier string `json:"identifier" validate:"required"`
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
AreaCode string `json:"area_code"`
}
AppAuthCheckResponse {
Status bool
}
AppAuthRequest {
Method string `json:"method" validate:"required" validate:"required,oneof=device email mobile"`
Account string `json:"account"`
Password string `json:"password"`
Identifier string `json:"identifier" validate:"required"`
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
Code string `json:"code"`
Invite string `json:"invite"`
AreaCode string `json:"area_code"`
CfToken string `json:"cf_token,optional"`
}
AppAuthRespone {
Token string `json:"token"`
}
AppSendCodeRequest {
Method string `json:"method" validate:"required" validate:"required,oneof=email mobile"`
Account string `json:"account"`
AreaCode string `json:"area_code"`
CfToken string `json:"cf_token,optional"`
}
AppSendCodeRespone {
Status bool `json:"status"`
Code string `json:"code,omitempty"`
}
AppConfigRequest {
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
}
AppConfigResponse {
EncryptionKey string `json:"encryption_key"`
EncryptionMethod string `json:"encryption_method"`
Domains []string `json:"domains"`
StartupPicture string `json:"startup_picture"`
StartupPictureSkipTime int64 `json:"startup_picture_skip_time"`
Application AppInfo `json:"applications"`
OfficialEmail string `json:"official_email"`
OfficialWebsite string `json:"official_website"`
OfficialTelegram string `json:"official_telegram"`
OfficialTelephone string `json:"official_telephone"`
InvitationLink string `json:"invitation_link"`
KrWebsiteId string `json:"kr_website_id"`
}
AppInfo {
Id int64 `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Url string `json:"url"`
Version string `json:"version"`
VersionDescription string `json:"version_description"`
IsDefault bool `json:"is_default"`
}
)
@server (
prefix: v1/app/auth
group: app/auth
middleware: AppMiddleware
)
service ppanel {
@doc "Check Account"
@handler Check
post /check (AppAuthCheckRequest) returns (AppAuthCheckResponse)
@doc "Login"
@handler Login
post /login (AppAuthRequest) returns (AppAuthRespone)
@doc "Register"
@handler Register
post /register (AppAuthRequest) returns (AppAuthRespone)
@doc "Reset Password"
@handler ResetPassword
post /reset_password (AppAuthRequest) returns (AppAuthRespone)
@doc "GetAppConfig"
@handler GetAppConfig
post /config (AppConfigRequest) returns (AppConfigResponse)
}

View File

@ -1,27 +0,0 @@
syntax = "v1"
info (
title: "Document API"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import "../types.api"
@server (
prefix: v1/app/document
group: app/document
middleware: AppMiddleware,AuthMiddleware
)
service ppanel {
@doc "Get document list"
@handler QueryDocumentList
get /list returns (QueryDocumentListResponse)
@doc "Get document detail"
@handler QueryDocumentDetail
get /detail (QueryDocumentDetailRequest) returns (Document)
}

View File

@ -1,40 +0,0 @@
syntax = "v1"
info (
title: "App Node Api"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import "../types.api"
type (
AppRuleGroupListResponse {
Total int64 `json:"total"`
List []ServerRuleGroup `json:"list"`
}
AppUserSubscbribeNodeRequest {
Id int64 `form:"id" validate:"required"`
}
AppUserSubscbribeNodeResponse {
List []AppUserSubscbribeNode `json:"list"`
}
)
@server (
prefix: v1/app/node
group: app/node
middleware: AppMiddleware,AuthMiddleware
)
service ppanel {
@doc "Get Node list"
@handler GetNodeList
get /list (AppUserSubscbribeNodeRequest) returns (AppUserSubscbribeNodeResponse)
@doc "Get rule group list"
@handler GetRuleGroupList
get /rule_group_list returns (AppRuleGroupListResponse)
}

View File

@ -1,57 +0,0 @@
syntax = "v1"
info (
title: "Order API"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import (
"../types.api"
)
@server (
prefix: v1/app/order
group: app/order
middleware: AppMiddleware,AuthMiddleware
)
service ppanel {
@doc "Pre create order"
@handler PreCreateOrder
post /pre (PurchaseOrderRequest) returns (PreOrderResponse)
@doc "purchase Subscription"
@handler Purchase
post /purchase (PurchaseOrderRequest) returns (PurchaseOrderResponse)
@doc "Renewal Subscription"
@handler Renewal
post /renewal (RenewalOrderRequest) returns (RenewalOrderResponse)
@doc "Reset traffic"
@handler ResetTraffic
post /reset (ResetTrafficOrderRequest) returns (ResetTrafficOrderResponse)
@doc "Recharge"
@handler Recharge
post /recharge (RechargeOrderRequest) returns (RechargeOrderResponse)
@doc "Checkout order"
@handler CheckoutOrder
post /checkout (CheckoutOrderRequest) returns (CheckoutOrderResponse)
@doc "Close order"
@handler CloseOrder
post /close (CloseOrderRequest)
@doc "Get order"
@handler QueryOrderDetail
get /detail (QueryOrderDetailRequest) returns (OrderDetail)
@doc "Get order list"
@handler QueryOrderList
get /list (QueryOrderListRequest) returns (QueryOrderListResponse)
}

View File

@ -1,23 +0,0 @@
syntax = "v1"
info (
title: "payment API"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import "../types.api"
@server (
prefix: v1/app/payment
group: app/payment
middleware: AppMiddleware,AuthMiddleware
)
service ppanel {
@doc "Get available payment methods"
@handler GetAvailablePaymentMethods
get /methods returns (GetAvailablePaymentMethodsResponse)
}

View File

@ -1,65 +0,0 @@
syntax = "v1"
info (
title: "Subscribe API"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import "../types.api"
type (
QueryUserSubscribeResp {
Data []UserSubscribeData `json:"data"`
}
UserSubscribeData {
SubscribeId int64 `json:"subscribe_id"`
UserSubscribeId int64 `json:"user_subscribe_id"`
}
UserSubscribeResetPeriodRequest {
UserSubscribeId int64 `json:"user_subscribe_id"`
}
UserSubscribeResetPeriodResponse {
Status bool `json:"status"`
}
AppUserSubscribeRequest {
ContainsNodes *bool `form:"contains_nodes"`
}
AppUserSubscbribeResponse {
List []AppUserSubcbribe `json:"list"`
}
)
@server (
prefix: v1/app/subscribe
group: app/subscribe
middleware: AppMiddleware,AuthMiddleware
)
service ppanel {
@doc "Get subscribe list"
@handler QuerySubscribeList
get /list returns (QuerySubscribeListResponse)
@doc "Get subscribe group list"
@handler QuerySubscribeGroupList
get /group/list returns (QuerySubscribeGroupListResponse)
@doc "Get application config"
@handler QueryApplicationConfig
get /application/config returns (ApplicationResponse)
@doc "Get Already subscribed to package"
@handler QueryUserAlreadySubscribe
get /user/already_subscribe returns (QueryUserSubscribeResp)
@doc "Get Available subscriptions for users"
@handler QueryUserAvailableUserSubscribe
get /user/available_subscribe (AppUserSubscribeRequest) returns (AppUserSubscbribeResponse)
@doc "Reset user subscription period"
@handler ResetUserSubscribePeriod
post /reset/period (UserSubscribeResetPeriodRequest) returns (UserSubscribeResetPeriodResponse)
}

View File

@ -1,86 +0,0 @@
syntax = "v1"
info (
title: "App User Api"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import (
"../types.api"
)
type (
UserInfoResponse {
Id int64 `json:"id"`
Balance int64 `json:"balance"`
Email string `json:"email"`
RefererId int64 `json:"referer_id"`
ReferCode string `json:"refer_code"`
Avatar string `json:"avatar"`
AreaCode string `json:"area_code"`
Telephone string `json:"telephone"`
Devices []UserDevice `json:"devices"`
AuthMethods []UserAuthMethod `json:"auth_methods"`
}
UpdatePasswordRequeset {
Password string `json:"password"`
NewPassword string `json:"new_password"`
}
DeleteAccountRequest {
Method string `json:"method" validate:"required" validate:"required,oneof=email telephone device"`
Code string `json:"code"`
}
GetUserOnlineTimeStatisticsResponse {
WeeklyStats []WeeklyStat `json:"weekly_stats"`
ConnectionRecords ConnectionRecords `json:"connection_records"`
}
WeeklyStat {
Day int `json:"day"`
DayName string `json:"day_name"`
Hours float64 `json:"hours"`
}
ConnectionRecords {
CurrentContinuousDays int64 `json:"current_continuous_days"`
HistoryContinuousDays int64 `json:"history_continuous_days"`
LongestSingleConnection int64 `json:"longest_single_connection"`
}
)
@server (
prefix: v1/app/user
group: app/user
middleware: AppMiddleware,AuthMiddleware
)
service ppanel {
@doc "query user info"
@handler QueryUserInfo
get /info returns (UserInfoResponse)
@doc "Update Password "
@handler UpdatePassword
put /password (UpdatePasswordRequeset)
@doc "Delete Account"
@handler DeleteAccount
delete /account (DeleteAccountRequest)
@doc "Get user subcribe traffic logs"
@handler GetUserSubscribeTrafficLogs
get /subscribe/traffic_logs (GetUserSubscribeTrafficLogsRequest) returns (GetUserSubscribeTrafficLogsResponse)
@doc "Get user online time total"
@handler GetUserOnlineTimeStatistics
get /online_time/statistics returns (GetUserOnlineTimeStatisticsResponse)
@doc "Query User Affiliate List"
@handler QueryUserAffiliateList
get /affiliate/list (QueryUserAffiliateListRequest) returns (QueryUserAffiliateListResponse)
@doc "Query User Affiliate Count"
@handler QueryUserAffiliate
get /affiliate/count returns (QueryUserAffiliateCountResponse)
}

View File

@ -1,21 +0,0 @@
syntax = "v1"
info (
title: "App Heartbeat Api"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
@server (
prefix: v1/app/ws
group: app/ws
middleware: AuthMiddleware
)
service ppanel {
@doc "App heartbeat"
@handler AppWs
get /:userid/:identifier
}

View File

@ -35,10 +35,6 @@ type (
GetTosResponse { GetTosResponse {
TosContent string `json:"tos_content"` TosContent string `json:"tos_content"`
} }
GetAppcationResponse {
Config ApplicationConfig `json:"config"`
Applications []ApplicationResponseInfo `json:"applications"`
}
// GetCodeRequest Get code request // GetCodeRequest Get code request
SendCodeRequest { SendCodeRequest {
Email string `json:"email" validate:"required"` Email string `json:"email" validate:"required"`
@ -102,10 +98,6 @@ service ppanel {
@handler GetGlobalConfig @handler GetGlobalConfig
get /site/config returns (GetGlobalConfigResponse) get /site/config returns (GetGlobalConfigResponse)
@doc "Get Tos Content"
@handler GetApplication
get /application returns (GetAppcationResponse)
@doc "Get Tos Content" @doc "Get Tos Content"
@handler GetTos @handler GetTos
get /site/tos returns (GetTosResponse) get /site/tos returns (GetTosResponse)

View File

@ -23,9 +23,5 @@ service ppanel {
@doc "Get subscribe group list" @doc "Get subscribe group list"
@handler QuerySubscribeGroupList @handler QuerySubscribeGroupList
get /group/list returns (QuerySubscribeGroupListResponse) get /group/list returns (QuerySubscribeGroupListResponse)
@doc "Get application config"
@handler QueryApplicationConfig
get /application/config returns (ApplicationResponse)
} }

View File

@ -1,22 +0,0 @@
syntax = "v1"
info (
title: "App API"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import (
"./app/auth.api"
"./app/user.api"
"./app/node.api"
"./app/ws.api"
"./app/order.api"
"./app/announcement.api"
"./app/payment.api"
"./app/document.api"
"./app/subscribe.api"
)

View File

@ -475,14 +475,6 @@ type (
Port int `json:"port"` Port int `json:"port"`
Prefix string `json:"prefix"` Prefix string `json:"prefix"`
} }
ApplicationConfig {
AppId int64 `json:"app_id"`
EncryptionKey string `json:"encryption_key"`
EncryptionMethod string `json:"encryption_method"`
Domains []string `json:"domains" validate:"required"`
StartupPicture string `json:"startup_picture"`
StartupPictureSkipTime int64 `json:"startup_picture_skip_time"`
}
UserDevice { UserDevice {
Id int64 `json:"id"` Id int64 `json:"id"`
Ip string `json:"ip"` Ip string `json:"ip"`

View File

@ -0,0 +1,3 @@
DROP TABLE IF EXISTS `application`;
DROP TABLE IF EXISTS `application_version`;
DROP TABLE IF EXISTS `application_config`;

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -22,15 +22,6 @@ import (
adminTicket "github.com/perfect-panel/server/internal/handler/admin/ticket" adminTicket "github.com/perfect-panel/server/internal/handler/admin/ticket"
adminTool "github.com/perfect-panel/server/internal/handler/admin/tool" adminTool "github.com/perfect-panel/server/internal/handler/admin/tool"
adminUser "github.com/perfect-panel/server/internal/handler/admin/user" 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" auth "github.com/perfect-panel/server/internal/handler/auth"
authOauth "github.com/perfect-panel/server/internal/handler/auth/oauth" authOauth "github.com/perfect-panel/server/internal/handler/auth/oauth"
common "github.com/perfect-panel/server/internal/handler/common" 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)) 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 // Get Currency Config
adminSystemGroupRouter.GET("/currency_config", adminSystem.GetCurrencyConfigHandler(serverCtx)) 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)) 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") authGroupRouter := router.Group("/v1/auth")
{ {
@ -759,9 +576,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// Get Ads // Get Ads
commonGroupRouter.GET("/ads", common.GetAdsHandler(serverCtx)) commonGroupRouter.GET("/ads", common.GetAdsHandler(serverCtx))
// Get Tos Content
commonGroupRouter.GET("/application", common.GetApplicationHandler(serverCtx))
// Check verification code // Check verification code
commonGroupRouter.POST("/check_verification_code", common.CheckVerificationCodeHandler(serverCtx)) 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)) publicSubscribeGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{ {
// Get application config
publicSubscribeGroupRouter.GET("/application/config", publicSubscribe.QueryApplicationConfigHandler(serverCtx))
// Get subscribe group list // Get subscribe group list
publicSubscribeGroupRouter.GET("/group/list", publicSubscribe.QuerySubscribeGroupListHandler(serverCtx)) publicSubscribeGroupRouter.GET("/group/list", publicSubscribe.QuerySubscribeGroupListHandler(serverCtx))

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

Some files were not shown because too many files have changed in this diff Show More