From 7dc241c37d7af95accc603682086e9b2c74e6415 Mon Sep 17 00:00:00 2001 From: guosl Date: Thu, 4 Jul 2024 23:49:41 +0800 Subject: [PATCH] =?UTF-8?q?1=20=E9=87=8D=E7=BD=AE=E5=AF=86=E7=A0=81=202=20?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/sql/init/user.sql | 1 + internal/models/user.go | 25 ++++++ internal/repo/user.go | 27 +++++++ internal/service/user/interface.go | 4 + internal/service/user/user.go | 126 ++++++++++++++++++++++++----- pkg/validator/custom_rules.go | 17 ++++ pkg/validator/validator.go | 4 + server/user/user.go | 18 +++++ 8 files changed, 204 insertions(+), 18 deletions(-) diff --git a/deploy/sql/init/user.sql b/deploy/sql/init/user.sql index 73a691a..1e42adf 100644 --- a/deploy/sql/init/user.sql +++ b/deploy/sql/init/user.sql @@ -8,6 +8,7 @@ CREATE TABLE IF NOT EXISTS `user` ( `pwd` varchar(255) DEFAULT NULL COMMENT '密码', `salt` varchar(32) NOT NULL COMMENT '盐', `sex` TINYINT DEFAULT 0 COMMENT '性别:0-女,1-男', + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0-禁用,1-启用', `created_by` VARCHAR(64) DEFAULT '' COMMENT '创建人', `created_on` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '记录创建时间', `modified_by` VARCHAR(64) DEFAULT '' COMMENT '修改人', diff --git a/internal/models/user.go b/internal/models/user.go index 6ab311a..401bec2 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -1,5 +1,12 @@ package models +type UserStatus int + +const ( + EnableUserStatus UserStatus = 0 + DisableUserStatus UserStatus = 1 +) + type LoginInfo struct { Account string Pwd string @@ -26,3 +33,21 @@ type User struct { Id uint UserInfo } + +type ModifyInfo struct { + Name string `json:"name" binding:"required"` + Sex int `json:"sex"` +} + +type Query struct { + Page int `json:"page" binding:"required"` + PageSize int `json:"page_size" binding:"required"` + Keyword string `Json:"keyword"` + Sort string `json:"sort" binding:"sql_sort"` +} + +type ResetPwdReq struct { + Id uint `json:"id" binging:"required"` + OldPwd string `json:"old_pwd" binding:"required"` + Pwd string `json:"pwd" binding:"required"` +} diff --git a/internal/repo/user.go b/internal/repo/user.go index db12d04..b113453 100644 --- a/internal/repo/user.go +++ b/internal/repo/user.go @@ -1,6 +1,7 @@ package repo import ( + "busniess-user-center/internal/models" "context" "fmt" "time" @@ -39,6 +40,9 @@ type UserRepo interface { GetUserByEmail(ctx context.Context, mobile string) (user User, err error) SaveUser(ctx context.Context, user User) error CreateUser(ctx context.Context, user *User) error + SetUserStatus(ctx context.Context, id uint, status models.UserStatus) error + Search(ctx context.Context, query *models.Query) ([]User, error) + ResetPwd(ctx context.Context, user User) error } type userRepoS struct { @@ -77,3 +81,26 @@ func (u *userRepoS) GetUserByEmail(ctx context.Context, email string) (user User err = u.db.Where("email = ?", email).Take(&user).Error return } + +func (u *userRepoS) SetUserStatus(ctx context.Context, id uint, status models.UserStatus) error { + err := u.db.Model(&User{}).Where("id = ?", id).Update("status", status).Error + return err +} + +func (u *userRepoS) Search(ctx context.Context, query *models.Query) ([]User, error) { + users := make([]User, 0) + + keyword := fmt.Sprintf("%%%s%%", query.Keyword) + db := u.db.Model(&User{}) + if query.Keyword != "" { + db = db.Where("account like ? or name like ?", keyword, keyword) + } + + err := db.Order(query.Sort).Limit(query.PageSize).Offset(query.Page * query.PageSize).Find(&users).Error + return users, err +} + +func (u *userRepoS) ResetPwd(ctx context.Context, user User) error { + err := u.db.Model(&User{}).Where("id = ?", user.ID).Updates(map[string]any{"pwd": user.Pwd, "salt": user.Salt}).Error + return err +} diff --git a/internal/service/user/interface.go b/internal/service/user/interface.go index 6547c5f..dd6fcd3 100644 --- a/internal/service/user/interface.go +++ b/internal/service/user/interface.go @@ -9,4 +9,8 @@ type UserService interface { Add(ctx context.Context, info *models.AddInfo) (id uint, err error) Login(ctx context.Context, lInfo models.LoginInfo) error Logout(ctx context.Context) error + Modify(ctx context.Context, mInfo *models.ModifyInfo) error + Disable(ctx context.Context) error + Enable(ctx context.Context) error + Search(ctx context.Context, query *models.Query) ([]models.User, error) } diff --git a/internal/service/user/user.go b/internal/service/user/user.go index 6169c40..9c8ca09 100644 --- a/internal/service/user/user.go +++ b/internal/service/user/user.go @@ -92,6 +92,7 @@ func (u *userService) Add(ctx context.Context, info *models.AddInfo) (id uint, e Email: info.Email, Pwd: pwd, Sex: info.Sex, + Salt: salt, CreatedBy: session.Account, } @@ -139,38 +140,127 @@ func (u *userService) Logout(ctx context.Context) error { return nil } -func (u *userService) Modify() error { +func (u *userService) Modify(ctx context.Context, mInfo *models.ModifyInfo) error { // 获取当前操作用户 + session, err := contextUtil.GetSession(ctx) + if err != nil { + return err + } + // 判断修改用户是否是同一个人 - return nil + user, err := u.repo.GetUserByAccount(ctx, session.Account) + if err != nil { + return err + } + + user.Name = mInfo.Name + user.Sex = mInfo.Sex + return u.repo.SaveUser(ctx, user) } -func (u *userService) Disable() error { +func (u *userService) Disable(ctx context.Context) error { // 获取操作用户 - // 判断是否有权限 + session, err := contextUtil.GetSession(ctx) + if err != nil { + return err + } + + // todo 判断是否有权限 + // 修改对应用户状态 - return nil + return u.repo.SetUserStatus(ctx, session.ID, models.DisableUserStatus) } -func (u *userService) Able() error { - // 获取操作用户 - // 判断是否有权限 +func (u *userService) Enable(ctx context.Context) error { + session, err := contextUtil.GetSession(ctx) + if err != nil { + return err + } + + // todo 判断是否有权限 + // 修改对应用户状态 - return nil + return u.repo.SetUserStatus(ctx, session.ID, models.EnableUserStatus) } -func (u *userService) Users() error { +func (u *userService) Search(ctx context.Context, query *models.Query) ([]models.User, error) { // 获取操作用户 - // 判断是否有权限 + _, err := contextUtil.GetSession(ctx) + if err != nil { + return nil, err + } + // 返回用户列表 + users, err := u.repo.Search(ctx, query) + if err != nil { + return nil, err + } + + list := convertUserList(users) + return list, err +} + +func (u *userService) ResetPwd(ctx context.Context, req *models.ResetPwdReq) error { + // 获取操作用户 + session, err := contextUtil.GetSession(ctx) + if err != nil { + return err + } + + // 判断是否本人操作 + rUser, err := u.repo.GetUserByAccount(ctx, session.Account) + if err != nil && err != gorm.ErrRecordNotFound { + return err + } + + if err == gorm.ErrRecordNotFound { + return fmt.Errorf("重置用户不存在") + } + + if session.ID != rUser.ID { + // 校验权限 + return fmt.Errorf("没权限") + } + + // 判断当前密码是否正确 + oldPwd := u.sha256(req.OldPwd, rUser.Salt) + if oldPwd != rUser.Pwd { + return fmt.Errorf("密码错误") + } + + rUser.Salt = stringUtil.RandStringRunes(saltLen) + rUser.Pwd = u.sha256(req.Pwd, rUser.Salt) + err = u.repo.ResetPwd(ctx, rUser) + if err != nil { + return fmt.Errorf("repo reset pwd fail:%s", err.Error()) + } + + // 生成新的密码并保存 + if err = u.tokenRefresher.DeleteToken(rUser.ID); err != nil { + return fmt.Errorf("token delete fail:%s", err.Error()) + } + return nil } -func (u *userService) ResetPwd() error { - // 获取操作用户 - // 判断是否本人操作 - // 判断当前密码是否正确 - // 生成新的密码并保存 - // 删除旧的缓存 - return nil +func convertUserList(users []repo.User) []models.User { + list := make([]models.User, len(users)) + for _, item := range users { + list = append(list, convertUser(item)) + } + + return list +} + +func convertUser(user repo.User) models.User { + return models.User{ + Id: user.ID, + UserInfo: models.UserInfo{ + Name: user.Name, + Account: user.Account, + Mobile: user.Mobile, + Email: user.Email, + Sex: user.Sex, + }, + } } diff --git a/pkg/validator/custom_rules.go b/pkg/validator/custom_rules.go index 336afa0..a02fe96 100644 --- a/pkg/validator/custom_rules.go +++ b/pkg/validator/custom_rules.go @@ -6,6 +6,10 @@ import ( "github.com/go-playground/validator/v10" ) +var ( + sortMatch = regexp.MustCompile("^[a-zA-z0-9_]+") +) + func tableName(fl validator.FieldLevel) bool { value := fl.Field().String() if value == "" { @@ -18,3 +22,16 @@ func tableName(fl validator.FieldLevel) bool { return false } + +func sortVerify(fl validator.FieldLevel) bool { + value := fl.Field().String() + if value == "" { + return false + } + + if isOk := sortMatch.MatchString(value); isOk { + return true + } + + return false +} diff --git a/pkg/validator/validator.go b/pkg/validator/validator.go index d1d1360..f37f294 100644 --- a/pkg/validator/validator.go +++ b/pkg/validator/validator.go @@ -92,6 +92,10 @@ func (c *customValidator) registerValidation() error { return err } + if err := c.validate.RegisterValidation("sql_sort", sortVerify); err != nil { + return err + } + return nil } diff --git a/server/user/user.go b/server/user/user.go index 5663baf..639b69f 100644 --- a/server/user/user.go +++ b/server/user/user.go @@ -34,6 +34,8 @@ func RegisterRoute(api *gin.RouterGroup) { api.POST("/add", ginUtil.Wrap(server.Add)) api.POST("/login", ginUtil.WrapNoRsp(server.Login)) api.POST("/logout", ginUtil.WrapNo(server.Logout)) + api.POST("/modify", ginUtil.WrapNoRsp(server.Modify)) + api.GET("/search", ginUtil.WrapNoRsp(server.Modify)) } func (u *UserServer) Add(ctx context.Context, req *models.AddInfo) (rsp proto.AddResponse, err error) { @@ -64,3 +66,19 @@ func (u *UserServer) Login(ctx context.Context, req *proto.LoginRequest) (err er func (u *UserServer) Logout(ctx context.Context) error { return u.userService.Logout(ctx) } + +func (u *UserServer) Modify(ctx context.Context, req *models.ModifyInfo) error { + return u.userService.Modify(ctx, req) +} + +func (u *UserServer) Disable(ctx context.Context) error { + return u.userService.Disable(ctx) +} + +func (u *UserServer) Enable(ctx context.Context) error { + return u.userService.Enable(ctx) +} + +func (u *UserServer) Search(ctx context.Context, query *models.Query) ([]models.User, error) { + return u.userService.Search(ctx, query) +}