382 lines
10 KiB
Go
382 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 {
|
||
// 超级管理员(888)直接通过
|
||
if adminAuthorityID == 888 {
|
||
return nil
|
||
}
|
||
|
||
// 获取管理员角色的所有子角色ID(递归)
|
||
authIDs, err := getStructAuthorityList(tx, adminAuthorityID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 检查目标角色是否在权限列表中
|
||
for _, id := range authIDs {
|
||
if id == targetAuthorityID {
|
||
return nil
|
||
}
|
||
}
|
||
return errors.New("您没有权限分配该角色")
|
||
}
|
||
|
||
// getStructAuthorityList 递归获取角色ID列表(包含子角色)
|
||
func getStructAuthorityList(tx *gorm.DB, authorityID uint) ([]uint, error) {
|
||
var auth model.SysAuthority
|
||
if err := tx.First(&auth, "authority_id = ?", authorityID).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var list []uint
|
||
var children []model.SysAuthority
|
||
if err := tx.Where("parent_id = ?", authorityID).Find(&children).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
for _, child := range children {
|
||
list = append(list, uint(child.AuthorityID))
|
||
childList, err := getStructAuthorityList(tx, uint(child.AuthorityID))
|
||
if err == nil {
|
||
list = append(list, childList...)
|
||
}
|
||
}
|
||
|
||
// 如果是顶级角色,包含自己
|
||
if auth.ParentID == 0 {
|
||
list = append(list, authorityID)
|
||
}
|
||
|
||
return list, 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 {
|
||
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
|
||
}
|
||
return authority.DefaultRouter, nil
|
||
}
|
||
|
||
// 转换函数
|
||
func toBizUser(u *system.User) *model.SysUser {
|
||
return &model.SysUser{
|
||
ID: int64(u.ID),
|
||
UUID: 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),
|
||
}
|
||
}
|
||
|
||
func toModelUser(m *model.SysUser) *system.User {
|
||
u := &system.User{
|
||
ID: uint(m.ID),
|
||
Username: m.Username,
|
||
Password: m.Password,
|
||
NickName: m.NickName,
|
||
HeaderImg: m.HeaderImg,
|
||
AuthorityId: uint(m.AuthorityID),
|
||
Phone: m.Phone,
|
||
Email: m.Email,
|
||
Enable: int(m.Enable),
|
||
OriginSetting: json.RawMessage(m.OriginSetting),
|
||
CreatedAt: m.CreatedAt,
|
||
UpdatedAt: m.UpdatedAt,
|
||
}
|
||
u.UUID, _ = uuid.Parse(m.UUID)
|
||
return u
|
||
}
|
||
|
||
func toModelUserWithAuthorities(m *model.SysUser) *system.User {
|
||
u := toModelUser(m)
|
||
|
||
// 转换Authority
|
||
u.Authority = &system.Authority{
|
||
AuthorityId: uint(m.Authority.AuthorityID),
|
||
AuthorityName: m.Authority.AuthorityName,
|
||
DefaultRouter: m.Authority.DefaultRouter,
|
||
}
|
||
if m.Authority.ParentID != 0 {
|
||
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: a.AuthorityName,
|
||
DefaultRouter: a.DefaultRouter,
|
||
}
|
||
if a.ParentID != 0 {
|
||
pid := uint(a.ParentID)
|
||
u.Authorities[i].ParentId = &pid
|
||
}
|
||
}
|
||
}
|
||
|
||
return u
|
||
}
|