diff --git a/apis/public/user.api b/apis/public/user.api index 92d0c19..45ebdef 100644 --- a/apis/public/user.api +++ b/apis/public/user.api @@ -108,6 +108,9 @@ type ( UserSubscribeId int64 `json:"user_subscribe_id" validate:"required"` Note string `json:"note" validate:"max=500"` } + UpdateUserRulesRequest { + Rules []string `json:"rules" validate:"required"` + } ) @server ( @@ -215,5 +218,9 @@ service ppanel { @doc "Update User Subscribe Note" @handler UpdateUserSubscribeNote put /subscribe_note (UpdateUserSubscribeNoteRequest) + + @doc "Update User Rules" + @handler UpdateUserRules + put /rules (UpdateUserRulesRequest) } diff --git a/apis/types.api b/apis/types.api index 3f50d02..0efa991 100644 --- a/apis/types.api +++ b/apis/types.api @@ -28,6 +28,7 @@ type ( EnableTradeNotify bool `json:"enable_trade_notify"` AuthMethods []UserAuthMethod `json:"auth_methods"` UserDevices []UserDevice `json:"user_devices"` + Rules []string `json:"rules"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` DeletedAt int64 `json:"deleted_at,omitempty"` diff --git a/initialize/migrate/database/02120_user_rules.down.sql b/initialize/migrate/database/02120_user_rules.down.sql new file mode 100644 index 0000000..718f4a6 --- /dev/null +++ b/initialize/migrate/database/02120_user_rules.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE `user` +DROP COLUMN IF EXISTS `rules`; diff --git a/initialize/migrate/database/02120_user_rules.up.sql b/initialize/migrate/database/02120_user_rules.up.sql new file mode 100644 index 0000000..5e93aca --- /dev/null +++ b/initialize/migrate/database/02120_user_rules.up.sql @@ -0,0 +1,4 @@ +ALTER TABLE `user` + ADD COLUMN `rules` TEXT NULL + COMMENT 'User rules for subscription' + AFTER `created_at`; diff --git a/internal/handler/public/user/updateUserRulesHandler.go b/internal/handler/public/user/updateUserRulesHandler.go new file mode 100644 index 0000000..e8b9a01 --- /dev/null +++ b/internal/handler/public/user/updateUserRulesHandler.go @@ -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) + } +} diff --git a/internal/handler/routes.go b/internal/handler/routes.go index 542d66c..7faf037 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -493,6 +493,9 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) { adminToolGroupRouter.Use(middleware.AuthMiddleware(serverCtx)) { + // Query IP Location + adminToolGroupRouter.GET("/ip/location", adminTool.QueryIPLocationHandler(serverCtx)) + // Get System Log adminToolGroupRouter.GET("/log", adminTool.GetSystemLogHandler(serverCtx)) @@ -822,6 +825,9 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) { // Update User Password publicUserGroupRouter.PUT("/password", publicUser.UpdateUserPasswordHandler(serverCtx)) + // Update User Rules + publicUserGroupRouter.PUT("/rules", publicUser.UpdateUserRulesHandler(serverCtx)) + // Query User Subscribe publicUserGroupRouter.GET("/subscribe", publicUser.QueryUserSubscribeHandler(serverCtx)) diff --git a/internal/logic/public/user/updateUserRulesLogic.go b/internal/logic/public/user/updateUserRulesLogic.go new file mode 100644 index 0000000..63ab169 --- /dev/null +++ b/internal/logic/public/user/updateUserRulesLogic.go @@ -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 +} diff --git a/internal/model/user/user.go b/internal/model/user/user.go index 3344745..ee9e6f9 100644 --- a/internal/model/user/user.go +++ b/internal/model/user/user.go @@ -25,6 +25,7 @@ type User struct { EnableTradeNotify *bool `gorm:"default:false;not null;comment:Enable Trade Notifications"` AuthMethods []AuthMethods `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"` UpdatedAt time.Time `gorm:"comment:Update Time"` } diff --git a/internal/types/types.go b/internal/types/types.go index 1c54b3f..f039294 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -1577,7 +1577,7 @@ type QueryIPLocationRequest struct { type QueryIPLocationResponse struct { Country string `json:"country"` - Region string `json:"regio,omitempty"` + Region string `json:"region,omitempty"` City string `json:"city"` } @@ -2479,6 +2479,10 @@ type UpdateUserPasswordRequest struct { Password string `json:"password" validate:"required"` } +type UpdateUserRulesRequest struct { + Rules []string `json:"rules" validate:"required"` +} + type UpdateUserSubscribeNoteRequest struct { UserSubscribeId int64 `json:"user_subscribe_id" validate:"required"` Note string `json:"note" validate:"max=500"` @@ -2517,6 +2521,7 @@ type User struct { EnableTradeNotify bool `json:"enable_trade_notify"` AuthMethods []UserAuthMethod `json:"auth_methods"` UserDevices []UserDevice `json:"user_devices"` + Rules []string `json:"rules"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` DeletedAt int64 `json:"deleted_at,omitempty"` @@ -2608,7 +2613,6 @@ type UserSubscribe struct { Token string `json:"token"` Status uint8 `json:"status"` Short string `json:"short"` - Note string `json:"note"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } @@ -2628,7 +2632,6 @@ type UserSubscribeDetail struct { Upload int64 `json:"upload"` Token string `json:"token"` Status uint8 `json:"status"` - Note string `json:"note"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } @@ -2647,7 +2650,6 @@ type UserSubscribeInfo struct { Upload int64 `json:"upload"` Token string `json:"token"` Status uint8 `json:"status"` - Note string `json:"note"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` IsTryOut bool `json:"is_try_out"`