DeployHelper/internal/service/sys_user_service.go

428 lines
12 KiB
Go

package service
import (
"ego/internal/model"
"ego/internal/serializer"
"ego/internal/types"
"ego/internal/util"
"ego/pkg/logger"
"fmt"
"time"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
const (
// PassWordCost 密码加密难度
PassWordCost = 12
// Suspend 被封禁用户
Suspend = "-1"
// Active 未激活用户
Active = "1"
// Inactive 激活用户
Inactive = "0"
)
// SysUserService 管理用户登录的服务
type SysUserService struct {
Db *gorm.DB
}
// NewSysUserService 构建用户登录服务
func NewSysUserService(db *gorm.DB) *SysUserService {
return &SysUserService{
Db: db,
}
}
type UserLoginRequest struct {
Account string `form:"account" json:"account" binding:"required,min=5,max=30"`
PassWord string `form:"password" json:"password" binding:"required,min=8,max=40"`
Checked *bool `form:"checked" json:"checked" binding:"required"`
Phone string `form:"phone" json:"phone"`
VerifyCode string `form:"verifyCode" json:"verifyCode"`
}
// UserRegisterRequest 用户注册表单验证
type UserRegisterRequest struct {
NickName string `form:"nickName" json:"nickName" binding:"required,min=2,max=30"`
UserName string `form:"userName" json:"userName" binding:"required,min=5,max=30"`
PassWord string `form:"passWord" json:"passWord" binding:"required,min=8,max=40"`
PasswordConfirm string `form:"passWordConfirm" json:"passWordConfirm" binding:"required,min=8,max=40"`
}
// Login 用户登录函数
func (s *SysUserService) Login(c *gin.Context) serializer.Response {
var user model.SysUser
u := UserLoginRequest{}
if err := c.ShouldBind(&u); err != nil {
logger.Error(c, "参数绑定错误!", zap.Error(err))
c.Set("msg", "参数绑定错误!")
return serializer.Err(serializer.CodeParamErr, "参数绑定错误!", err)
}
c.Set("account", u.Account)
if err := s.Db.Where("user_name = ?", u.Account).First(&user).Error; err != nil {
logger.Error(c, "账号或密码错误!")
c.Set("msg", "账号或密码错误!")
return serializer.ParamErr("账号或密码错误!", nil)
}
if user.Status == Suspend {
logger.Error(c, "账号已封禁!")
c.Set("msg", "账号已封禁!")
return serializer.ParamErr("账号已封禁!", nil)
}
if user.Status == Inactive {
logger.Error(c, "账号未激活!")
c.Set("msg", "账号未激活!")
return serializer.ParamErr("账号未激活!", nil)
}
if !CheckPassWord(u.PassWord, user.PassWord) {
logger.Error(c, "账号或密码错误!")
c.Set("msg", "账号或密码错误!")
return serializer.ParamErr("账号或密码错误!", nil)
}
if token, err := util.GenerateToken(user.UserId, user.UserName); err == nil {
logger.Info(c, "用户登录", zap.String("redisKey", util.TokenGroup+user.UserName))
// 删除key
del := util.Del(c, util.TokenGroup+user.UserName)
if del != nil {
logger.Error(c, "redis 删除失败!", zap.Error(del))
c.Set("msg", "redis 删除失败!")
return serializer.ParamErr("系统繁忙稍后重试!", nil)
}
// 结果放入redis
set := util.Set(c, util.TokenGroup+user.UserName, token, time.Hour*24)
if set != nil {
logger.Error(c, "redis 放入失败!", zap.Error(set))
c.Set("msg", "redis 放入失败!")
return serializer.ParamErr("系统繁忙稍后重试!", nil)
}
c.Set("status", Active)
return types.BuildUserResponseHasToken(user, token)
}
return serializer.ParamErr("系统繁忙稍后重试!", nil)
}
// UserLogout 退出登录
func (s *SysUserService) UserLogout(c *gin.Context) serializer.Response {
// 退出登录
go func() {
tokenString := c.GetHeader("Authorization")
token, err := util.ParseToken(tokenString[8:])
if err == nil {
username := token["username"].(string)
// 删除key
if err := util.Del(c, util.TokenGroup+username); err != nil {
logger.Error(c, "退出登录失败!", zap.Error(err))
} else {
logger.Info(c, "用户退出登录成功!", zap.String("redisKey", util.TokenGroup+username))
}
}
}()
return serializer.Succ("退出登录成功!", true)
}
// GetUser 用ID获取用户
func GetUser(id string, d *gorm.DB) (model.SysUser, error) {
var user model.SysUser
result := d.Where("user_id = ?", id).First(&user)
if result.Error == nil {
user.PassWord = "" // 清除密码
}
return user, result.Error
}
// SetPassWord 设置密码
func SetPassWord(passWord string, sysUser *model.SysUser) error {
bytes, err := bcrypt.GenerateFromPassword([]byte(passWord), PassWordCost)
if err != nil {
return err
}
sysUser.PassWord = string(bytes)
return nil
}
// CheckPassWord 校验密码
func CheckPassWord(password string, passwordDigest string) bool {
err := bcrypt.CompareHashAndPassword([]byte(passwordDigest), []byte(password))
return err == nil
}
// valid 验证表单
func (s *SysUserService) valid(u *UserRegisterRequest) *serializer.Response {
if u.PasswordConfirm != u.PassWord {
return &serializer.Response{
Code: 40001,
Msg: "两次输入的密码不相同",
}
}
count := int64(0)
s.Db.Model(&model.SysUser{}).Where("nick_name = ?", u.NickName).Count(&count)
if count > 0 {
return &serializer.Response{
Code: 40001,
Msg: "昵称被占用",
}
}
count = 0
s.Db.Model(&model.SysUser{}).Where("user_name = ?", u.UserName).Count(&count)
if count > 0 {
return &serializer.Response{
Code: 40001,
Msg: "用户名已经注册",
}
}
return nil
}
// Register 用户注册
func (s *SysUserService) Register(c *gin.Context) serializer.Response {
u := UserRegisterRequest{}
if err := c.ShouldBind(&u); err != nil {
return serializer.Err(serializer.CodeParamErr, "参数绑定错误!", err)
}
now := time.Now()
user := model.SysUser{
NickName: u.NickName,
UserName: u.UserName,
Status: Active,
CreateTime: &now,
}
// 生成ID
if id, err := SysSequenceServiceBuilder(user.TableName()).GenerateId(); err == nil {
user.UserId = id
} else {
return serializer.DBErr("序列生成失败!", err)
}
// 表单验证
if err := s.valid(&u); err != nil {
logger.Error(c, err.Msg, zap.String("NickName", u.NickName), zap.String("UserName", u.UserName))
return *err
}
// 密码加密
if err := SetPassWord(u.PassWord, &user); err != nil {
logger.Error(c, "密码加密失败!")
return serializer.Err(serializer.CodeEncryptError, "密码加密失败!", err)
}
// 使用事务封装数据库操作
err := s.Db.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&user).Error; err != nil {
return err
}
return nil
})
if err != nil {
logger.Error(c, "注册失败!")
return serializer.ParamErr("注册失败", err)
}
return types.BuildUserResponse(user)
}
// Create 创建用户
func (s *SysUserService) Create(c *gin.Context) serializer.Response {
var user model.SysUser
if err := c.ShouldBind(&user); err != nil {
logger.Error(c, "参数绑定失败!")
return serializer.ParamErr("参数绑定失败!", err)
}
if user.Status == "" {
user.Status = Active
}
now := time.Now()
user.CreateTime = &now
createBy := c.GetString("id")
user.CreateBy = createBy
id, err := SysSequenceServiceBuilder(user.TableName()).GenerateId()
if err != nil {
return serializer.DBErr("创建用户失败!", err)
}
user.UserId = id
if err := s.Db.Create(&user).Error; err != nil {
logger.Error(c, "创建用户失败!")
return serializer.DBErr("创建用户失败!", err)
}
return serializer.Succ("创建用户成功!", user)
}
// DeleteByID 根据ID删除用户
func (s *SysUserService) DeleteByID(c *gin.Context) serializer.Response {
id := c.Param("id")
if id == "" {
logger.Error(c, "id 不可为空!")
}
// 删除逻辑
data := map[string]any{
"del_flag": "1",
"update_time": time.Now(),
"update_by": c.GetString("id"),
}
var user model.SysUser
if err := s.Db.Model(&user).Where("user_id = ?", id).Updates(data).Error; err != nil {
logger.Error(c, "未查询用户信息!")
return serializer.DBErr("删除用户失败!", err)
}
return serializer.Succ("删除用户成功!", user)
}
// UpdateByID 根据ID更新用户
func (s *SysUserService) UpdateByID(c *gin.Context) serializer.Response {
var user model.SysUser
if err := c.ShouldBind(&user); err != nil {
logger.Error(c, "参数绑定失败!")
return serializer.ParamErr("参数绑定失败!", err)
}
id := user.UserId
if id == "" {
logger.Error(c, "id 不可为空!")
return serializer.ParamErr("id不可为空!", fmt.Errorf("id不可为空"))
}
if err := s.Db.Model(&user).Where("user_id = ?", id).Updates(&user).Error; err != nil {
logger.Error(c, "更新用户信息失败!")
return serializer.DBErr("更新用户信息失败!", err)
}
return serializer.Succ("更新用户信息成功!", user)
}
// GetByID 根据ID获取用户
func (s *SysUserService) GetByID(c *gin.Context) serializer.Response {
var user model.SysUser
if err := s.Db.Where("user_id = ?", c.Param("id")).First(&user).Error; err != nil {
logger.Error(c, "获取用户信息失败!")
return serializer.DBErr("获取用户信息失败!", err)
}
user.PassWord = "" // 清除密码
return serializer.Succ("查询成功!", user)
}
// DeleteByIDs 批量删除用户
func (s *SysUserService) DeleteByIDs(c *gin.Context) serializer.Response {
var ids types.Payload
if err := c.ShouldBind(&ids); err != nil {
return serializer.ParamErr("参数绑定失败!", err)
}
// 删除逻辑
data := map[string]any{
"del_flag": "1",
"update_time": time.Now(),
"update_by": c.GetString("id"),
}
if err := s.Db.Model(&model.SysUser{}).Where("user_id in (?)", ids.Ids).Updates(data).Error; err != nil {
logger.Error(c, "批量删除用户失败!")
return serializer.DBErr("批量删除用户失败!", err)
}
return serializer.Succ("批量删除用户成功!", nil)
}
// GetByCondition 条件查询用户
func (s *SysUserService) GetByCondition(c *gin.Context) serializer.Response {
var p types.Params
if err := c.ShouldBind(&p); err != nil {
return serializer.ParamErr("参数绑定失败!", err)
}
queryStr, args, err := p.ConvertToGormConditions()
if err != nil {
logger.Error(c, "参数绑定失败!")
return serializer.ParamErr("参数绑定失败!", err)
}
var total int64
var users []model.SysUser
offset := (p.Page - 1) * p.Limit
// 构建基础查询
db := s.Db.Model(&model.SysUser{})
// 如果有查询条件,添加条件
if queryStr != "" {
db = db.Where(queryStr, args...)
}
// 排序
if p.Sort != "" {
db = db.Order(p.Sort)
}
// 执行分页查询
if err := db.Where("del_flag = ?", "0").Offset(offset).Limit(p.Limit).Find(&users).Error; err != nil {
logger.Error(c, "获取用户信息失败!")
return serializer.DBErr("获取用户信息失败!", err)
}
// 清除所有用户的密码
for i := range users {
users[i].PassWord = ""
}
// 执行总数查询
if err := db.Where("del_flag = ?", "0").Count(&total).Error; err != nil {
logger.Error(c, "获取用户总数失败!")
return serializer.DBErr("获取用户总数失败!", err)
}
return serializer.Succ("查询成功!", gin.H{
"total": total,
"items": users,
"page": p.Page,
"limit": p.Limit,
})
}
// ListByIDs 根据ID列表获取用户
func (s *SysUserService) ListByIDs(c *gin.Context) serializer.Response {
var ids types.Payload
if err := c.ShouldBind(&ids); err != nil {
return serializer.ParamErr("参数绑定失败!", err)
}
var users []model.SysUser
if err := s.Db.Where("user_id in (?)", ids.Ids).Find(&users).Error; err != nil {
logger.Error(c, "获取用户信息失败!")
return serializer.DBErr("获取用户信息失败!", err)
}
// 清除所有用户的密码
for i := range users {
users[i].PassWord = ""
}
return serializer.Succ("查询成功!", users)
}
// CurrentUser 获取当前用户
func (s *SysUserService) CurrentUser(c *gin.Context) (*model.SysUser, error) {
tokenString := c.GetHeader("Authorization")
var user model.SysUser
token, err := util.ParseToken(tokenString[8:])
if err != nil {
return nil, fmt.Errorf("获取当前用户失败! %v", err)
}
id := token["id"].(string)
if err := s.Db.Model(&user).Where("user_id = ?", id).First(&user).Error; err != nil {
logger.Error(c, "获取当前用户失败!", zap.Error(err))
return nil, err
}
// 清除密码
user.PassWord = ""
return &user, nil
}