feat(user): add endpoint and logic for updating user rules

This commit is contained in:
Chang lue Tsen 2025-11-24 09:05:49 -05:00
parent b29e5c8cb5
commit 429e535dd4
9 changed files with 104 additions and 4 deletions

View File

@ -108,6 +108,9 @@ type (
UserSubscribeId int64 `json:"user_subscribe_id" validate:"required"` UserSubscribeId int64 `json:"user_subscribe_id" validate:"required"`
Note string `json:"note" validate:"max=500"` Note string `json:"note" validate:"max=500"`
} }
UpdateUserRulesRequest {
Rules []string `json:"rules" validate:"required"`
}
) )
@server ( @server (
@ -215,5 +218,9 @@ service ppanel {
@doc "Update User Subscribe Note" @doc "Update User Subscribe Note"
@handler UpdateUserSubscribeNote @handler UpdateUserSubscribeNote
put /subscribe_note (UpdateUserSubscribeNoteRequest) put /subscribe_note (UpdateUserSubscribeNoteRequest)
@doc "Update User Rules"
@handler UpdateUserRules
put /rules (UpdateUserRulesRequest)
} }

View File

@ -28,6 +28,7 @@ type (
EnableTradeNotify bool `json:"enable_trade_notify"` EnableTradeNotify bool `json:"enable_trade_notify"`
AuthMethods []UserAuthMethod `json:"auth_methods"` AuthMethods []UserAuthMethod `json:"auth_methods"`
UserDevices []UserDevice `json:"user_devices"` UserDevices []UserDevice `json:"user_devices"`
Rules []string `json:"rules"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
DeletedAt int64 `json:"deleted_at,omitempty"` DeletedAt int64 `json:"deleted_at,omitempty"`

View File

@ -0,0 +1,2 @@
ALTER TABLE `user`
DROP COLUMN IF EXISTS `rules`;

View File

@ -0,0 +1,4 @@
ALTER TABLE `user`
ADD COLUMN `rules` TEXT NULL
COMMENT 'User rules for subscription'
AFTER `created_at`;

View File

@ -0,0 +1,26 @@
package user
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/public/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Update User Rules
func UpdateUserRulesHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.UpdateUserRulesRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := user.NewUpdateUserRulesLogic(c.Request.Context(), svcCtx)
err := l.UpdateUserRules(&req)
result.HttpResult(c, nil, err)
}
}

View File

@ -493,6 +493,9 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
adminToolGroupRouter.Use(middleware.AuthMiddleware(serverCtx)) adminToolGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{ {
// Query IP Location
adminToolGroupRouter.GET("/ip/location", adminTool.QueryIPLocationHandler(serverCtx))
// Get System Log // Get System Log
adminToolGroupRouter.GET("/log", adminTool.GetSystemLogHandler(serverCtx)) adminToolGroupRouter.GET("/log", adminTool.GetSystemLogHandler(serverCtx))
@ -822,6 +825,9 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// Update User Password // Update User Password
publicUserGroupRouter.PUT("/password", publicUser.UpdateUserPasswordHandler(serverCtx)) publicUserGroupRouter.PUT("/password", publicUser.UpdateUserPasswordHandler(serverCtx))
// Update User Rules
publicUserGroupRouter.PUT("/rules", publicUser.UpdateUserRulesHandler(serverCtx))
// Query User Subscribe // Query User Subscribe
publicUserGroupRouter.GET("/subscribe", publicUser.QueryUserSubscribeHandler(serverCtx)) publicUserGroupRouter.GET("/subscribe", publicUser.QueryUserSubscribeHandler(serverCtx))

View File

@ -0,0 +1,51 @@
package user
import (
"context"
"encoding/json"
"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 UpdateUserRulesLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// NewUpdateUserRulesLogic Update User Rules
func NewUpdateUserRulesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateUserRulesLogic {
return &UpdateUserRulesLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *UpdateUserRulesLogic) UpdateUserRules(req *types.UpdateUserRulesRequest) error {
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
if !ok {
logger.Error("current user is not found in context")
return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
}
if len(req.Rules) > 0 {
bytes, err := json.Marshal(req.Rules)
if err != nil {
l.Logger.Errorf("UpdateUserRulesLogic json marshal rules error: %v", err)
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "json marshal rules failed: %v", err.Error())
}
u.Rules = string(bytes)
err = l.svcCtx.UserModel.Update(l.ctx, u)
if err != nil {
l.Logger.Errorf("UpdateUserRulesLogic UpdateUserRules error: %v", err)
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update user rules failed: %v", err.Error())
}
}
return nil
}

View File

@ -25,6 +25,7 @@ type User struct {
EnableTradeNotify *bool `gorm:"default:false;not null;comment:Enable Trade Notifications"` EnableTradeNotify *bool `gorm:"default:false;not null;comment:Enable Trade Notifications"`
AuthMethods []AuthMethods `gorm:"foreignKey:UserId;references:Id"` AuthMethods []AuthMethods `gorm:"foreignKey:UserId;references:Id"`
UserDevices []Device `gorm:"foreignKey:UserId;references:Id"` UserDevices []Device `gorm:"foreignKey:UserId;references:Id"`
Rules string `gorm:"type:TEXT;comment:User Rules"`
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"` CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`
UpdatedAt time.Time `gorm:"comment:Update Time"` UpdatedAt time.Time `gorm:"comment:Update Time"`
} }

View File

@ -1577,7 +1577,7 @@ type QueryIPLocationRequest struct {
type QueryIPLocationResponse struct { type QueryIPLocationResponse struct {
Country string `json:"country"` Country string `json:"country"`
Region string `json:"regio,omitempty"` Region string `json:"region,omitempty"`
City string `json:"city"` City string `json:"city"`
} }
@ -2479,6 +2479,10 @@ type UpdateUserPasswordRequest struct {
Password string `json:"password" validate:"required"` Password string `json:"password" validate:"required"`
} }
type UpdateUserRulesRequest struct {
Rules []string `json:"rules" validate:"required"`
}
type UpdateUserSubscribeNoteRequest struct { type UpdateUserSubscribeNoteRequest struct {
UserSubscribeId int64 `json:"user_subscribe_id" validate:"required"` UserSubscribeId int64 `json:"user_subscribe_id" validate:"required"`
Note string `json:"note" validate:"max=500"` Note string `json:"note" validate:"max=500"`
@ -2517,6 +2521,7 @@ type User struct {
EnableTradeNotify bool `json:"enable_trade_notify"` EnableTradeNotify bool `json:"enable_trade_notify"`
AuthMethods []UserAuthMethod `json:"auth_methods"` AuthMethods []UserAuthMethod `json:"auth_methods"`
UserDevices []UserDevice `json:"user_devices"` UserDevices []UserDevice `json:"user_devices"`
Rules []string `json:"rules"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
DeletedAt int64 `json:"deleted_at,omitempty"` DeletedAt int64 `json:"deleted_at,omitempty"`
@ -2608,7 +2613,6 @@ type UserSubscribe struct {
Token string `json:"token"` Token string `json:"token"`
Status uint8 `json:"status"` Status uint8 `json:"status"`
Short string `json:"short"` Short string `json:"short"`
Note string `json:"note"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
} }
@ -2628,7 +2632,6 @@ type UserSubscribeDetail struct {
Upload int64 `json:"upload"` Upload int64 `json:"upload"`
Token string `json:"token"` Token string `json:"token"`
Status uint8 `json:"status"` Status uint8 `json:"status"`
Note string `json:"note"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
} }
@ -2647,7 +2650,6 @@ type UserSubscribeInfo struct {
Upload int64 `json:"upload"` Upload int64 `json:"upload"`
Token string `json:"token"` Token string `json:"token"`
Status uint8 `json:"status"` Status uint8 `json:"status"`
Note string `json:"note"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
IsTryOut bool `json:"is_try_out"` IsTryOut bool `json:"is_try_out"`