kra/internal/data/system/user.go

390 lines
10 KiB
Go

package system
import (
"context"
"encoding/json"
"errors"
"kra/internal/biz/system"
"kra/internal/data/model"
"kra/internal/data/query"
"github.com/google/uuid"
"gorm.io/gorm"
)
type userRepo struct {
db *gorm.DB
}
// NewUserRepo 创建用户仓储
func NewUserRepo(db *gorm.DB) system.UserRepo {
query.SetDefault(db)
return &userRepo{db: db}
}
func (r *userRepo) Create(ctx context.Context, user *system.User) error {
m := toBizUser(user)
return query.SysUser.WithContext(ctx).Create(m)
}
func (r *userRepo) Update(ctx context.Context, user *system.User) error {
_, err := query.SysUser.WithContext(ctx).Where(query.SysUser.ID.Eq(int64(user.ID))).Updates(map[string]any{
"nick_name": user.NickName,
"header_img": user.HeaderImg,
"phone": user.Phone,
"email": user.Email,
"enable": user.Enable,
})
return err
}
func (r *userRepo) UpdateSelf(ctx context.Context, user *system.User) error {
updates := map[string]any{}
if user.NickName != "" {
updates["nick_name"] = user.NickName
}
if user.HeaderImg != "" {
updates["header_img"] = user.HeaderImg
}
if user.Phone != "" {
updates["phone"] = user.Phone
}
if user.Email != "" {
updates["email"] = user.Email
}
if user.SideMode != "" {
updates["side_mode"] = user.SideMode
}
if user.BaseColor != "" {
updates["base_color"] = user.BaseColor
}
if len(updates) == 0 {
return nil
}
_, err := query.SysUser.WithContext(ctx).Where(query.SysUser.ID.Eq(int64(user.ID))).Updates(updates)
return err
}
func (r *userRepo) UpdateSelfSetting(ctx context.Context, id uint, setting json.RawMessage) error {
_, err := query.SysUser.WithContext(ctx).Where(query.SysUser.ID.Eq(int64(id))).Update(query.SysUser.OriginSetting, string(setting))
return err
}
func (r *userRepo) Delete(ctx context.Context, id uint) error {
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Where("id = ?", id).Delete(&model.SysUser{}).Error; err != nil {
return err
}
if err := tx.Where("sys_user_id = ?", id).Delete(&model.SysUserAuthority{}).Error; err != nil {
return err
}
return nil
})
}
func (r *userRepo) FindByID(ctx context.Context, id uint) (*system.User, error) {
m, err := query.SysUser.WithContext(ctx).Where(query.SysUser.ID.Eq(int64(id))).First()
if err != nil {
return nil, err
}
return toModelUser(m), nil
}
func (r *userRepo) FindByIDWithAuthorities(ctx context.Context, id uint) (*system.User, error) {
m, err := query.SysUser.WithContext(ctx).
Preload(query.SysUser.Authority).
Preload(query.SysUser.Authorities).
Where(query.SysUser.ID.Eq(int64(id))).
First()
if err != nil {
return nil, err
}
return toModelUserWithAuthorities(m), nil
}
func (r *userRepo) FindByUUID(ctx context.Context, uuidStr string) (*system.User, error) {
m, err := query.SysUser.WithContext(ctx).Where(query.SysUser.UUID.Eq(uuidStr)).First()
if err != nil {
return nil, err
}
return toModelUser(m), nil
}
func (r *userRepo) FindByUUIDWithAuthorities(ctx context.Context, uuidStr string) (*system.User, error) {
m, err := query.SysUser.WithContext(ctx).
Preload(query.SysUser.Authority).
Preload(query.SysUser.Authorities).
Where(query.SysUser.UUID.Eq(uuidStr)).
First()
if err != nil {
return nil, err
}
return toModelUserWithAuthorities(m), nil
}
func (r *userRepo) FindByUsername(ctx context.Context, username string) (*system.User, error) {
m, err := query.SysUser.WithContext(ctx).Where(query.SysUser.Username.Eq(username)).First()
if err != nil {
return nil, err
}
return toModelUser(m), nil
}
func (r *userRepo) FindByUsernameWithAuthorities(ctx context.Context, username string) (*system.User, error) {
m, err := query.SysUser.WithContext(ctx).
Preload(query.SysUser.Authority).
Preload(query.SysUser.Authorities).
Where(query.SysUser.Username.Eq(username)).
First()
if err != nil {
return nil, err
}
return toModelUserWithAuthorities(m), nil
}
func (r *userRepo) List(ctx context.Context, page, pageSize int, filters map[string]string) ([]*system.User, int64, error) {
u := query.SysUser
q := u.WithContext(ctx)
if v, ok := filters["username"]; ok && v != "" {
q = q.Where(u.Username.Like("%" + v + "%"))
}
if v, ok := filters["nick_name"]; ok && v != "" {
q = q.Where(u.NickName.Like("%" + v + "%"))
}
if v, ok := filters["phone"]; ok && v != "" {
q = q.Where(u.Phone.Like("%" + v + "%"))
}
if v, ok := filters["email"]; ok && v != "" {
q = q.Where(u.Email.Like("%" + v + "%"))
}
total, err := q.Count()
if err != nil {
return nil, 0, err
}
offset := (page - 1) * pageSize
list, err := q.Preload(u.Authority).Preload(u.Authorities).Offset(offset).Limit(pageSize).Find()
if err != nil {
return nil, 0, err
}
users := make([]*system.User, len(list))
for i := range list {
users[i] = toModelUserWithAuthorities(list[i])
}
return users, total, nil
}
func (r *userRepo) UpdatePassword(ctx context.Context, id uint, password string) error {
return r.db.WithContext(ctx).Model(&model.SysUser{}).Where("id = ?", id).Update("password", password).Error
}
func (r *userRepo) UpdateAuthorityID(ctx context.Context, id uint, authorityId uint) error {
return r.db.WithContext(ctx).Model(&model.SysUser{}).Where("id = ?", id).Update("authority_id", authorityId).Error
}
func (r *userRepo) SetUserAuthorities(ctx context.Context, adminAuthorityID, userId uint, authorityIds []uint) error {
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
var user model.SysUser
if err := tx.Where("id = ?", userId).First(&user).Error; err != nil {
return errors.New("查询用户数据失败")
}
if err := tx.Where("sys_user_id = ?", userId).Delete(&model.SysUserAuthority{}).Error; err != nil {
return err
}
for _, aid := range authorityIds {
if err := checkAuthorityIDAuth(tx, adminAuthorityID, aid); err != nil {
return err
}
ua := &model.SysUserAuthority{
SysUserID: int64(userId),
SysAuthorityAuthorityID: int64(aid),
}
if err := tx.Create(ua).Error; err != nil {
return err
}
}
if len(authorityIds) > 0 {
if err := tx.Model(&model.SysUser{}).Where("id = ?", userId).Update("authority_id", authorityIds[0]).Error; err != nil {
return err
}
}
return nil
})
}
func checkAuthorityIDAuth(tx *gorm.DB, adminAuthorityID, targetAuthorityID uint) error {
if adminAuthorityID == 888 {
return nil
}
var authority model.SysAuthority
if err := tx.Where("authority_id = ? AND parent_id = ?", targetAuthorityID, adminAuthorityID).First(&authority).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("您没有权限分配该角色")
}
return err
}
return nil
}
func (r *userRepo) CheckUserHasAuthority(ctx context.Context, userId, authorityId uint) (bool, error) {
var count int64
err := r.db.WithContext(ctx).Model(&model.SysUserAuthority{}).
Where("sys_user_id = ? AND sys_authority_authority_id = ?", userId, authorityId).
Count(&count).Error
return count > 0, err
}
func (r *userRepo) GetAuthorityMenuRouters(ctx context.Context, authorityId uint) ([]string, error) {
var authorityMenus []model.SysAuthorityMenu
if err := r.db.WithContext(ctx).Where("sys_authority_authority_id = ?", authorityId).Find(&authorityMenus).Error; err != nil {
return nil, err
}
if len(authorityMenus) == 0 {
return []string{}, nil
}
menuIDs := make([]int64, len(authorityMenus))
for i, am := range authorityMenus {
menuIDs[i] = am.SysBaseMenuID
}
var menus []model.SysBaseMenu
if err := r.db.WithContext(ctx).Where("id IN ?", menuIDs).Find(&menus).Error; err != nil {
return nil, err
}
routers := make([]string, len(menus))
for i, m := range menus {
if m.Name != nil {
routers[i] = *m.Name
}
}
return routers, nil
}
func (r *userRepo) GetAuthorityDefaultRouter(ctx context.Context, authorityId uint) (string, error) {
var authority model.SysAuthority
if err := r.db.WithContext(ctx).Where("authority_id = ?", authorityId).First(&authority).Error; err != nil {
return "", err
}
if authority.DefaultRouter != nil {
return *authority.DefaultRouter, nil
}
return "", nil
}
// 转换函数
func toBizUser(u *system.User) *model.SysUser {
uuidStr := u.UUID.String()
username := u.Username
password := u.Password
nickName := u.NickName
headerImg := u.HeaderImg
authorityID := int64(u.AuthorityId)
phone := u.Phone
email := u.Email
enable := int64(u.Enable)
return &model.SysUser{
ID: int64(u.ID),
UUID: &uuidStr,
Username: &username,
Password: &password,
NickName: &nickName,
HeaderImg: &headerImg,
AuthorityID: &authorityID,
Phone: &phone,
Email: &email,
Enable: &enable,
}
}
func toModelUser(m *model.SysUser) *system.User {
u := &system.User{ID: uint(m.ID)}
if m.UUID != nil {
u.UUID, _ = uuid.Parse(*m.UUID)
}
if m.Username != nil {
u.Username = *m.Username
}
if m.Password != nil {
u.Password = *m.Password
}
if m.NickName != nil {
u.NickName = *m.NickName
}
if m.HeaderImg != nil {
u.HeaderImg = *m.HeaderImg
}
if m.AuthorityID != nil {
u.AuthorityId = uint(*m.AuthorityID)
}
if m.Phone != nil {
u.Phone = *m.Phone
}
if m.Email != nil {
u.Email = *m.Email
}
if m.Enable != nil {
u.Enable = int(*m.Enable)
}
if m.OriginSetting != nil {
u.OriginSetting = json.RawMessage(*m.OriginSetting)
}
if m.CreatedAt != nil {
u.CreatedAt = *m.CreatedAt
}
if m.UpdatedAt != nil {
u.UpdatedAt = *m.UpdatedAt
}
return u
}
func toModelUserWithAuthorities(m *model.SysUser) *system.User {
u := toModelUser(m)
// 转换Authority
u.Authority = &system.Authority{
AuthorityId: uint(m.Authority.AuthorityID),
AuthorityName: safeString(m.Authority.AuthorityName),
DefaultRouter: safeString(m.Authority.DefaultRouter),
}
if m.Authority.ParentID != nil {
pid := uint(*m.Authority.ParentID)
u.Authority.ParentId = &pid
}
// 转换Authorities
if len(m.Authorities) > 0 {
u.Authorities = make([]*system.Authority, len(m.Authorities))
for i, a := range m.Authorities {
u.Authorities[i] = &system.Authority{
AuthorityId: uint(a.AuthorityID),
AuthorityName: safeString(a.AuthorityName),
DefaultRouter: safeString(a.DefaultRouter),
}
if a.ParentID != nil {
pid := uint(*a.ParentID)
u.Authorities[i].ParentId = &pid
}
}
}
return u
}
func safeString(s *string) string {
if s == nil {
return ""
}
return *s
}