Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79ab4460bc |
@@ -239,6 +239,30 @@ type (
|
|||||||
OccurredAt int64 `json:"occurred_at"`
|
OccurredAt int64 `json:"occurred_at"`
|
||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
GetLogMessageRawRequest {
|
||||||
|
Id int64 `form:"id" validate:"required"`
|
||||||
|
}
|
||||||
|
GetLogMessageRawResponse {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
AppVersion string `json:"app_version"`
|
||||||
|
OsName string `json:"os_name"`
|
||||||
|
OsVersion string `json:"os_version"`
|
||||||
|
DeviceId string `json:"device_id"`
|
||||||
|
UserId *int64 `json:"user_id"`
|
||||||
|
SessionId string `json:"session_id"`
|
||||||
|
Level uint8 `json:"level"`
|
||||||
|
ErrorCode string `json:"error_code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Stack string `json:"stack"`
|
||||||
|
Context interface{} `json:"context"`
|
||||||
|
ClientIP string `json:"client_ip"`
|
||||||
|
UserAgent string `json:"user_agent"`
|
||||||
|
Locale string `json:"locale"`
|
||||||
|
Digest string `json:"digest"`
|
||||||
|
OccurredAt int64 `json:"occurred_at"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@server (
|
@server (
|
||||||
@@ -314,5 +338,9 @@ service ppanel {
|
|||||||
@doc "Get error log message detail"
|
@doc "Get error log message detail"
|
||||||
@handler GetErrorLogMessageDetail
|
@handler GetErrorLogMessageDetail
|
||||||
get /error_message/detail returns (GetErrorLogMessageDetailResponse)
|
get /error_message/detail returns (GetErrorLogMessageDetailResponse)
|
||||||
|
|
||||||
|
@doc "Get log message raw detail (temporary)"
|
||||||
|
@handler GetLogMessageRaw
|
||||||
|
get /message/detail (GetLogMessageRawRequest) returns (GetLogMessageRawResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -41,17 +41,17 @@ type (
|
|||||||
UserId int64 `json:"user_id" validate:"required"`
|
UserId int64 `json:"user_id" validate:"required"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Avatar string `json:"avatar"`
|
Avatar string `json:"avatar"`
|
||||||
Balance *int64 `json:"balance"`
|
Balance int64 `json:"balance"`
|
||||||
Commission *int64 `json:"commission"`
|
Commission int64 `json:"commission"`
|
||||||
ReferralPercentage uint8 `json:"referral_percentage"`
|
ReferralPercentage uint8 `json:"referral_percentage"`
|
||||||
OnlyFirstPurchase *bool `json:"only_first_purchase"`
|
OnlyFirstPurchase *bool `json:"only_first_purchase"`
|
||||||
GiftAmount *int64 `json:"gift_amount"`
|
GiftAmount int64 `json:"gift_amount"`
|
||||||
Telegram int64 `json:"telegram"`
|
Telegram int64 `json:"telegram"`
|
||||||
ReferCode string `json:"refer_code"`
|
ReferCode string `json:"refer_code"`
|
||||||
RefererId *int64 `json:"referer_id"`
|
RefererId int64 `json:"referer_id"`
|
||||||
Enable *bool `json:"enable"`
|
Enable *bool `json:"enable"`
|
||||||
IsAdmin *bool `json:"is_admin"`
|
IsAdmin *bool `json:"is_admin"`
|
||||||
Remark *string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
}
|
}
|
||||||
UpdateUserNotifySettingRequest {
|
UpdateUserNotifySettingRequest {
|
||||||
UserId int64 `json:"user_id" validate:"required"`
|
UserId int64 `json:"user_id" validate:"required"`
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/perfect-panel/server/internal/logic/admin/log"
|
||||||
|
"github.com/perfect-panel/server/internal/svc"
|
||||||
|
"github.com/perfect-panel/server/internal/types"
|
||||||
|
"github.com/perfect-panel/server/pkg/result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetLogMessageRawHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
var req types.GetLogMessageRawRequest
|
||||||
|
_ = c.ShouldBind(&req)
|
||||||
|
if err := svcCtx.Validate(&req); err != nil {
|
||||||
|
result.ParamErrorResult(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := log.NewGetLogMessageRawLogic(c.Request.Context(), svcCtx)
|
||||||
|
resp, err := l.GetLogMessageRaw(&req)
|
||||||
|
result.HttpResult(c, resp, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -256,6 +256,9 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
|
|||||||
// Get error log message detail
|
// Get error log message detail
|
||||||
adminLogGroupRouter.GET("/error_message/detail", adminLog.GetErrorLogMessageDetailHandler(serverCtx))
|
adminLogGroupRouter.GET("/error_message/detail", adminLog.GetErrorLogMessageDetailHandler(serverCtx))
|
||||||
|
|
||||||
|
// Get log message raw detail (temporary)
|
||||||
|
adminLogGroupRouter.GET("/message/detail", adminLog.GetLogMessageRawHandler(serverCtx))
|
||||||
|
|
||||||
// Get error log message list
|
// Get error log message list
|
||||||
adminLogGroupRouter.GET("/error_message/list", adminLog.GetErrorLogMessageListHandler(serverCtx))
|
adminLogGroupRouter.GET("/error_message/list", adminLog.GetErrorLogMessageListHandler(serverCtx))
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
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/xerr"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetLogMessageRawLogic struct {
|
||||||
|
logger.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetLogMessageRawLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLogMessageRawLogic {
|
||||||
|
return &GetLogMessageRawLogic{Logger: logger.WithContext(ctx), ctx: ctx, svcCtx: svcCtx}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetLogMessageRawLogic) GetLogMessageRaw(req *types.GetLogMessageRawRequest) (resp *types.GetLogMessageRawResponse, err error) {
|
||||||
|
row, err := l.svcCtx.LogMessageModel.FindOne(l.ctx, req.Id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "FindOne log_message id=%d: %v", req.Id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var contextJSON json.RawMessage
|
||||||
|
if row.Context != "" {
|
||||||
|
if json.Valid([]byte(row.Context)) {
|
||||||
|
contextJSON = json.RawMessage(row.Context)
|
||||||
|
} else {
|
||||||
|
b, _ := json.Marshal(row.Context)
|
||||||
|
contextJSON = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var occurredAt int64
|
||||||
|
if row.OccurredAt != nil {
|
||||||
|
occurredAt = row.OccurredAt.UnixMilli()
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.GetLogMessageRawResponse{
|
||||||
|
Id: row.Id,
|
||||||
|
Platform: row.Platform,
|
||||||
|
AppVersion: row.AppVersion,
|
||||||
|
OsName: row.OsName,
|
||||||
|
OsVersion: row.OsVersion,
|
||||||
|
DeviceId: row.DeviceId,
|
||||||
|
UserId: row.UserId,
|
||||||
|
SessionId: row.SessionId,
|
||||||
|
Level: row.Level,
|
||||||
|
ErrorCode: row.ErrorCode,
|
||||||
|
Message: row.Message,
|
||||||
|
Stack: row.Stack,
|
||||||
|
Context: contextJSON,
|
||||||
|
ClientIP: row.ClientIP,
|
||||||
|
UserAgent: row.UserAgent,
|
||||||
|
Locale: row.Locale,
|
||||||
|
Digest: row.Digest,
|
||||||
|
OccurredAt: occurredAt,
|
||||||
|
CreatedAt: row.CreatedAt.UnixMilli(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -46,13 +46,13 @@ func (l *UpdateUserBasicInfoLogic) UpdateUserBasicInfo(req *types.UpdateUserBasi
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = l.svcCtx.UserModel.Transaction(l.ctx, func(tx *gorm.DB) error {
|
err = l.svcCtx.UserModel.Transaction(l.ctx, func(tx *gorm.DB) error {
|
||||||
if req.Balance != nil && userInfo.Balance != *req.Balance {
|
if userInfo.Balance != req.Balance {
|
||||||
change := *req.Balance - userInfo.Balance
|
change := req.Balance - userInfo.Balance
|
||||||
balanceLog := log.Balance{
|
balanceLog := log.Balance{
|
||||||
Type: log.BalanceTypeAdjust,
|
Type: log.BalanceTypeAdjust,
|
||||||
Amount: change,
|
Amount: change,
|
||||||
OrderNo: "",
|
OrderNo: "",
|
||||||
Balance: *req.Balance,
|
Balance: req.Balance,
|
||||||
Timestamp: time.Now().UnixMilli(),
|
Timestamp: time.Now().UnixMilli(),
|
||||||
}
|
}
|
||||||
content, _ := balanceLog.Marshal()
|
content, _ := balanceLog.Marshal()
|
||||||
@@ -66,14 +66,14 @@ func (l *UpdateUserBasicInfoLogic) UpdateUserBasicInfo(req *types.UpdateUserBasi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userInfo.Balance = *req.Balance
|
userInfo.Balance = req.Balance
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.GiftAmount != nil && userInfo.GiftAmount != *req.GiftAmount {
|
if userInfo.GiftAmount != req.GiftAmount {
|
||||||
change := *req.GiftAmount - userInfo.GiftAmount
|
change := req.GiftAmount - userInfo.GiftAmount
|
||||||
if change != 0 {
|
if change != 0 {
|
||||||
var changeType uint16
|
var changeType uint16
|
||||||
if userInfo.GiftAmount < *req.GiftAmount {
|
if userInfo.GiftAmount < req.GiftAmount {
|
||||||
changeType = log.GiftTypeIncrease
|
changeType = log.GiftTypeIncrease
|
||||||
} else {
|
} else {
|
||||||
changeType = log.GiftTypeReduce
|
changeType = log.GiftTypeReduce
|
||||||
@@ -81,7 +81,7 @@ func (l *UpdateUserBasicInfoLogic) UpdateUserBasicInfo(req *types.UpdateUserBasi
|
|||||||
giftLog := log.Gift{
|
giftLog := log.Gift{
|
||||||
Type: changeType,
|
Type: changeType,
|
||||||
Amount: change,
|
Amount: change,
|
||||||
Balance: *req.GiftAmount,
|
Balance: req.GiftAmount,
|
||||||
Remark: "Admin adjustment",
|
Remark: "Admin adjustment",
|
||||||
Timestamp: time.Now().UnixMilli(),
|
Timestamp: time.Now().UnixMilli(),
|
||||||
}
|
}
|
||||||
@@ -96,27 +96,23 @@ func (l *UpdateUserBasicInfoLogic) UpdateUserBasicInfo(req *types.UpdateUserBasi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userInfo.GiftAmount = *req.GiftAmount
|
userInfo.GiftAmount = req.GiftAmount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Commission != nil && *req.Commission != userInfo.Commission {
|
if req.Commission != userInfo.Commission {
|
||||||
remark := ""
|
if isWithdrawalScene(req.Remark) {
|
||||||
if req.Remark != nil {
|
|
||||||
remark = *req.Remark
|
|
||||||
}
|
|
||||||
if isWithdrawalScene(remark) {
|
|
||||||
logWithdrawalGuard(l.Logger, userInfo.Id)
|
logWithdrawalGuard(l.Logger, userInfo.Id)
|
||||||
return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "commission overwrite is blocked in withdrawal scene")
|
return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "commission overwrite is blocked in withdrawal scene")
|
||||||
}
|
}
|
||||||
change := *req.Commission - userInfo.Commission
|
change := req.Commission - userInfo.Commission
|
||||||
if err = l.svcCtx.UserModel.UpdateCommission(l.ctx, userInfo.Id, change, tx); err != nil {
|
if err = l.svcCtx.UserModel.UpdateCommission(l.ctx, userInfo.Id, change, tx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = logicCommon.WriteCommissionLog(tx, userInfo.Id, log.CommissionTypeAdjust, change, ""); err != nil {
|
if err = logicCommon.WriteCommissionLog(tx, userInfo.Id, log.CommissionTypeAdjust, change, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userInfo.Commission = *req.Commission
|
userInfo.Commission = req.Commission
|
||||||
}
|
}
|
||||||
if req.Avatar != "" {
|
if req.Avatar != "" {
|
||||||
userInfo.Avatar = req.Avatar
|
userInfo.Avatar = req.Avatar
|
||||||
@@ -124,17 +120,15 @@ func (l *UpdateUserBasicInfoLogic) UpdateUserBasicInfo(req *types.UpdateUserBasi
|
|||||||
if req.ReferCode != "" {
|
if req.ReferCode != "" {
|
||||||
userInfo.ReferCode = req.ReferCode
|
userInfo.ReferCode = req.ReferCode
|
||||||
}
|
}
|
||||||
if req.RefererId != nil {
|
userInfo.RefererId = req.RefererId
|
||||||
userInfo.RefererId = *req.RefererId
|
|
||||||
}
|
|
||||||
if req.Enable != nil {
|
if req.Enable != nil {
|
||||||
userInfo.Enable = req.Enable
|
userInfo.Enable = req.Enable
|
||||||
}
|
}
|
||||||
if req.IsAdmin != nil {
|
if req.IsAdmin != nil {
|
||||||
userInfo.IsAdmin = req.IsAdmin
|
userInfo.IsAdmin = req.IsAdmin
|
||||||
}
|
}
|
||||||
if req.Remark != nil {
|
if req.Remark != "" {
|
||||||
userInfo.Remark = *req.Remark
|
userInfo.Remark = req.Remark
|
||||||
}
|
}
|
||||||
if req.OnlyFirstPurchase != nil {
|
if req.OnlyFirstPurchase != nil {
|
||||||
userInfo.OnlyFirstPurchase = req.OnlyFirstPurchase
|
userInfo.OnlyFirstPurchase = req.OnlyFirstPurchase
|
||||||
|
|||||||
+33
-5
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
type ActivateOrderRequest struct {
|
type ActivateOrderRequest struct {
|
||||||
OrderNo string `json:"order_no" validate:"required"`
|
OrderNo string `json:"order_no" validate:"required"`
|
||||||
}
|
}
|
||||||
@@ -3226,17 +3228,17 @@ type UpdateUserBasiceInfoRequest struct {
|
|||||||
UserId int64 `json:"user_id" validate:"required"`
|
UserId int64 `json:"user_id" validate:"required"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Avatar string `json:"avatar"`
|
Avatar string `json:"avatar"`
|
||||||
Balance *int64 `json:"balance"`
|
Balance int64 `json:"balance"`
|
||||||
Commission *int64 `json:"commission"`
|
Commission int64 `json:"commission"`
|
||||||
ReferralPercentage uint8 `json:"referral_percentage"`
|
ReferralPercentage uint8 `json:"referral_percentage"`
|
||||||
OnlyFirstPurchase *bool `json:"only_first_purchase"`
|
OnlyFirstPurchase *bool `json:"only_first_purchase"`
|
||||||
GiftAmount *int64 `json:"gift_amount"`
|
GiftAmount int64 `json:"gift_amount"`
|
||||||
Telegram int64 `json:"telegram"`
|
Telegram int64 `json:"telegram"`
|
||||||
ReferCode string `json:"refer_code"`
|
ReferCode string `json:"refer_code"`
|
||||||
RefererId *int64 `json:"referer_id"`
|
RefererId int64 `json:"referer_id"`
|
||||||
Enable *bool `json:"enable"`
|
Enable *bool `json:"enable"`
|
||||||
IsAdmin *bool `json:"is_admin"`
|
IsAdmin *bool `json:"is_admin"`
|
||||||
Remark *string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateUserNotifyRequest struct {
|
type UpdateUserNotifyRequest struct {
|
||||||
@@ -3641,3 +3643,29 @@ type GetAdminUserInviteListResponse struct {
|
|||||||
Total int64 `json:"total"`
|
Total int64 `json:"total"`
|
||||||
List []AdminInvitedUser `json:"list"`
|
List []AdminInvitedUser `json:"list"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetLogMessageRawRequest struct {
|
||||||
|
Id int64 `form:"id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetLogMessageRawResponse struct {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
AppVersion string `json:"app_version"`
|
||||||
|
OsName string `json:"os_name"`
|
||||||
|
OsVersion string `json:"os_version"`
|
||||||
|
DeviceId string `json:"device_id"`
|
||||||
|
UserId *int64 `json:"user_id"`
|
||||||
|
SessionId string `json:"session_id"`
|
||||||
|
Level uint8 `json:"level"`
|
||||||
|
ErrorCode string `json:"error_code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Stack string `json:"stack"`
|
||||||
|
Context json.RawMessage `json:"context"`
|
||||||
|
ClientIP string `json:"client_ip"`
|
||||||
|
UserAgent string `json:"user_agent"`
|
||||||
|
Locale string `json:"locale"`
|
||||||
|
Digest string `json:"digest"`
|
||||||
|
OccurredAt int64 `json:"occurred_at"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUpdateUserBasiceInfoRequestDistinguishesOmittedAndEmptyRemark(t *testing.T) {
|
|
||||||
var omitted UpdateUserBasiceInfoRequest
|
|
||||||
if err := json.Unmarshal([]byte(`{"user_id":1001}`), &omitted); err != nil {
|
|
||||||
t.Fatalf("unmarshal omitted remark: %v", err)
|
|
||||||
}
|
|
||||||
if omitted.Remark != nil {
|
|
||||||
t.Fatalf("omitted remark should stay nil, got %q", *omitted.Remark)
|
|
||||||
}
|
|
||||||
if omitted.RefererId != nil {
|
|
||||||
t.Fatalf("omitted referer_id should stay nil, got %d", *omitted.RefererId)
|
|
||||||
}
|
|
||||||
if omitted.Balance != nil || omitted.GiftAmount != nil || omitted.Commission != nil {
|
|
||||||
t.Fatalf("omitted money fields should stay nil, got balance=%v gift=%v commission=%v", omitted.Balance, omitted.GiftAmount, omitted.Commission)
|
|
||||||
}
|
|
||||||
|
|
||||||
var cleared UpdateUserBasiceInfoRequest
|
|
||||||
if err := json.Unmarshal([]byte(`{"user_id":1001,"remark":""}`), &cleared); err != nil {
|
|
||||||
t.Fatalf("unmarshal empty remark: %v", err)
|
|
||||||
}
|
|
||||||
if cleared.Remark == nil {
|
|
||||||
t.Fatal("explicit empty remark should be present")
|
|
||||||
}
|
|
||||||
if *cleared.Remark != "" {
|
|
||||||
t.Fatalf("explicit empty remark should decode to empty string, got %q", *cleared.Remark)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user