github.com/SupenBysz/gf-admin-community@v0.7.4/internal/logic/sys_role/sys_role.go (about)

     1  package sys_role
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"github.com/SupenBysz/gf-admin-community/sys_consts"
     7  	"github.com/SupenBysz/gf-admin-community/sys_model"
     8  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_dao"
     9  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_do"
    10  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_entity"
    11  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_enum"
    12  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_hook"
    13  	"github.com/SupenBysz/gf-admin-community/sys_service"
    14  	"github.com/gogf/gf/v2/container/garray"
    15  	"github.com/gogf/gf/v2/database/gdb"
    16  	"github.com/gogf/gf/v2/errors/gcode"
    17  	"github.com/gogf/gf/v2/errors/gerror"
    18  	"github.com/gogf/gf/v2/frame/g"
    19  	"github.com/gogf/gf/v2/os/gtime"
    20  	"github.com/gogf/gf/v2/util/gconv"
    21  	"github.com/kysion/base-library/base_hook"
    22  	"github.com/kysion/base-library/base_model"
    23  	"github.com/kysion/base-library/utility/base_funs"
    24  	"github.com/kysion/base-library/utility/daoctl"
    25  	"github.com/yitter/idgenerator-go/idgen"
    26  	"time"
    27  )
    28  
    29  type sSysRole struct {
    30  	conf gdb.CacheOption
    31  
    32  	// 修改团队成员Hook
    33  	RoleMemberHook base_hook.BaseHook[sys_enum.RoleMemberChange, sys_hook.RoleMemberChangeHookFunc]
    34  }
    35  
    36  func init() {
    37  	sys_service.RegisterSysRole(New())
    38  }
    39  
    40  func New() *sSysRole {
    41  	return &sSysRole{
    42  		conf: gdb.CacheOption{
    43  			Duration: time.Hour,
    44  			Force:    false,
    45  		},
    46  	}
    47  }
    48  
    49  // InstallInviteRegisterHook 订阅邀约注册Hook
    50  func (s *sSysRole) InstallInviteRegisterHook(action sys_enum.RoleMemberChange, hookFunc sys_hook.RoleMemberChangeHookFunc) {
    51  	s.RoleMemberHook.InstallHook(action, hookFunc)
    52  }
    53  
    54  // QueryRoleList 获取角色列表
    55  func (s *sSysRole) QueryRoleList(ctx context.Context, info base_model.SearchParams, unionMainId int64) (*sys_model.RoleListRes, error) {
    56  	// 自己商角色列表
    57  	info.Filter = append(info.Filter, base_model.FilterInfo{
    58  		Field:       sys_dao.SysRole.Columns().UnionMainId,
    59  		Where:       "=",
    60  		IsOrWhere:   false,
    61  		Value:       unionMainId,
    62  		IsNullValue: false,
    63  	})
    64  
    65  	cacheName := ""
    66  
    67  	for _, item := range info.Filter {
    68  		cacheName += item.Field + item.Where + gconv.String(item.Value)
    69  	}
    70  
    71  	result, err := daoctl.Query[*sys_entity.SysRole](sys_dao.SysRole.Ctx(ctx), &info, false)
    72  
    73  	return (*sys_model.RoleListRes)(result), err
    74  }
    75  
    76  // GetRoleById 根据id获取角色
    77  func (s *sSysRole) GetRoleById(ctx context.Context, id int64) (*sys_entity.SysRole, error) {
    78  	result, err := daoctl.GetByIdWithError[sys_entity.SysRole](sys_dao.SysRole.Ctx(ctx), id)
    79  
    80  	if err != nil {
    81  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "根据id获取角色失败", sys_dao.SysRole.Table())
    82  	}
    83  
    84  	return result, nil
    85  }
    86  
    87  // Create 创建角色信息
    88  func (s *sSysRole) Create(ctx context.Context, info sys_model.SysRole) (*sys_entity.SysRole, error) {
    89  	info.Id = 0
    90  	return s.Save(ctx, info)
    91  }
    92  
    93  // Update 更新角色信息
    94  func (s *sSysRole) Update(ctx context.Context, info sys_model.SysRole) (*sys_entity.SysRole, error) {
    95  	if info.Id <= 0 {
    96  		return nil, sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "ID参数错误"), "", sys_dao.SysRole.Table())
    97  	}
    98  	return s.Save(ctx, info)
    99  }
   100  
   101  // Save 新增或保存角色信息
   102  func (s *sSysRole) Save(ctx context.Context, info sys_model.SysRole) (*sys_entity.SysRole, error) {
   103  	roleInfo := sys_entity.SysRole{
   104  		Id:          info.Id,
   105  		Name:        info.Name,
   106  		Description: info.Description,
   107  		UnionMainId: info.UnionMainId,
   108  		IsSystem:    info.IsSystem,
   109  		UpdatedAt:   gtime.Now(),
   110  	}
   111  
   112  	err := sys_dao.SysRole.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   113  		if roleInfo.Id == 0 {
   114  			roleInfo.Id = idgen.NextId()
   115  
   116  			count, err := sys_dao.SysRole.Ctx(ctx).Where(sys_do.SysRole{Name: info.Name, UnionMainId: info.UnionMainId}).Count()
   117  			if err != nil {
   118  				return sys_service.SysLogs().ErrorSimple(ctx, err, "创建角色失败", sys_dao.SysRole.Table())
   119  			}
   120  
   121  			// 通过Union_main_id去判断
   122  			if count > 0 {
   123  				return sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "角色名称在该域已经存在"), "", sys_dao.SysRole.Table())
   124  			}
   125  
   126  			roleInfo.CreatedAt = gtime.Now()
   127  
   128  			// 清除缓存
   129  			_, err = sys_dao.SysRole.Ctx(ctx).Insert(roleInfo)
   130  
   131  			if err != nil {
   132  				return err
   133  			}
   134  
   135  			result, err := sys_service.Casbin().AddRoleForUserInDomain(gconv.String(roleInfo.Id), sys_consts.CasbinSuperRole, sys_consts.CasbinDomain)
   136  
   137  			if !result || err != nil {
   138  				return err
   139  			}
   140  		} else {
   141  			_, err := sys_dao.SysRole.Ctx(ctx).OmitNilData().Where(sys_do.SysRole{Id: roleInfo.Id}).Update(sys_do.SysRole{
   142  				Name:        roleInfo.Name,
   143  				Description: roleInfo.Description,
   144  				UpdatedAt:   roleInfo.UpdatedAt,
   145  			})
   146  			if err != nil {
   147  				return sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "保存角色失败"), "", sys_dao.SysRole.Table())
   148  			}
   149  		}
   150  
   151  		return nil
   152  	})
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	err = sys_dao.SysRole.Ctx(ctx).Where(sys_do.SysRole{Id: roleInfo.Id}).Scan(&roleInfo)
   158  
   159  	if err != nil {
   160  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "查询角色信息失败", sys_dao.SysRole.Table())
   161  	}
   162  
   163  	return &roleInfo, nil
   164  }
   165  
   166  // Delete 删除角色信息
   167  func (s *sSysRole) Delete(ctx context.Context, roleId int64) (bool, error) {
   168  	info := &sys_entity.SysRole{}
   169  	err := sys_dao.SysRole.Ctx(ctx).Where(sys_do.SysRole{Id: roleId}).Scan(&info)
   170  
   171  	if err != nil {
   172  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "删除角色失败", sys_dao.SysRole.Table())
   173  	}
   174  
   175  	if info.IsSystem {
   176  		return false, sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "系统默认的角色不能删除"), "", sys_dao.SysRole.Table())
   177  	}
   178  
   179  	userIds, err := sys_service.Casbin().Enforcer().GetRoleManager().GetUsers(gconv.String(roleId), sys_consts.CasbinDomain)
   180  
   181  	if len(userIds) > 0 {
   182  		return false, sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "删除角色失败,请先删除角色下的用户"), "", sys_dao.SysRole.Table())
   183  	}
   184  
   185  	if info.Id == 0 {
   186  		return false, sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "删除角色ID不存在"), "", sys_dao.SysRole.Table())
   187  	}
   188  
   189  	err = sys_dao.SysRole.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   190  		_, err = sys_dao.SysRole.Ctx(ctx).Delete(sys_do.SysRole{Id: roleId})
   191  
   192  		result, err := sys_service.Casbin().DeleteRoleForUserInDomain(gconv.String(info.Id), sys_consts.CasbinSuperRole, sys_consts.CasbinDomain)
   193  
   194  		if !result || err != nil {
   195  			return sys_service.SysLogs().ErrorSimple(ctx, err, "删除角色失败", sys_dao.SysRole.Table())
   196  		}
   197  		// 清除角色权限
   198  		sys_service.Casbin().DeletePermissionsForUser(gconv.String(info.Id))
   199  		return nil
   200  	})
   201  
   202  	return err == nil, err
   203  }
   204  
   205  // SetRoleMember 设置角色用户
   206  func (s *sSysRole) SetRoleMember(ctx context.Context, roleId int64, userIds []int64, makeUserUnionMainId int64) (bool, error) {
   207  	roleInfo := sys_entity.SysRole{}
   208  	err := sys_dao.SysRole.Ctx(ctx).Where(sys_do.SysRole{Id: roleId}).Scan(&roleInfo)
   209  
   210  	if err != nil {
   211  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "角色ID错误", sys_dao.SysRole.Table())
   212  	}
   213  
   214  	// 判断是否跨商
   215  	if makeUserUnionMainId != roleInfo.UnionMainId {
   216  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "禁止跨商操作", sys_dao.SysRole.Table())
   217  	}
   218  
   219  	err = sys_dao.SysRole.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   220  		for _, userId := range userIds {
   221  			userInfo, err := sys_service.SysUser().GetSysUserById(ctx, userId)
   222  
   223  			if err != nil {
   224  				return sys_service.SysLogs().ErrorSimple(ctx, err, "用户ID错误", sys_dao.SysRole.Table())
   225  			}
   226  
   227  			ret, _ := sys_service.Casbin().AddRoleForUserInDomain(gconv.String(userInfo.Id), gconv.String(roleInfo.Id), sys_consts.CasbinDomain)
   228  			if ret == true {
   229  				// 重置用户角色名称,并自动去重
   230  				userInfo.RoleNames = garray.NewSortedStrArrayFrom(append(userInfo.RoleNames, roleInfo.Name)).Unique().Slice()
   231  			}
   232  		}
   233  		return nil
   234  	})
   235  	return err == nil, err
   236  }
   237  
   238  // RemoveRoleMember 移除角色中的用户
   239  func (s *sSysRole) RemoveRoleMember(ctx context.Context, roleId int64, userIds []int64) (bool, error) {
   240  	roleInfo := sys_entity.SysRole{}
   241  	err := sys_dao.SysRole.Ctx(ctx).Where(sys_do.SysRole{Id: roleId}).Scan(&roleInfo)
   242  
   243  	if err != nil {
   244  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "角色ID错误", sys_dao.SysRole.Table())
   245  	}
   246  
   247  	err = sys_dao.SysRole.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   248  		for _, userId := range userIds {
   249  			userInfo, _ := sys_service.SysUser().GetSysUserById(ctx, userId)
   250  			if err != nil || userInfo == nil {
   251  				return sys_service.SysLogs().ErrorSimple(ctx, err, "用户ID错误", sys_dao.SysRole.Table())
   252  			}
   253  
   254  			//userInfo.RoleNames
   255  			//user := sys_service.SysSession().Get(ctx).JwtClaimsUser // 这样只能避免自己操作自己,别人操作自己就避免不了
   256  			//if user.IsAdmin && userId == user.Id {
   257  			//}
   258  
   259  			// 不能将系统的个管理员移除出系统默认的管理员角色 (Hook方案解决)
   260  			s.RoleMemberHook.Iterator(func(key sys_enum.RoleMemberChange, value sys_hook.RoleMemberChangeHookFunc) {
   261  				// 判断注入的Hook业务类型是否一致
   262  				if key.Code()&sys_enum.Role.Change.Remove.Code() == sys_enum.Role.Change.Remove.Code() {
   263  					// 业务类型一致则调用注入的Hook函数
   264  					g.Try(ctx, func(ctx context.Context) {
   265  						canRemove, err2 := value(ctx, sys_enum.Role.Change.Remove, roleInfo, userInfo)
   266  						if err2 != nil && canRemove == false {
   267  							err = err2
   268  							return
   269  						}
   270  					})
   271  				}
   272  			})
   273  
   274  			if err != nil {
   275  				return err
   276  			}
   277  
   278  			ret, err := sys_service.Casbin().DeleteRoleForUserInDomain(gconv.String(userInfo.Id), gconv.String(roleInfo.Id), sys_consts.CasbinDomain)
   279  			if err != nil {
   280  				return sys_service.SysLogs().ErrorSimple(ctx, err, "移除角色成员失败", sys_dao.SysRole.Table())
   281  			}
   282  
   283  			if ret == true {
   284  				// 重置用户角色名称,并自动去重
   285  				userInfo.RoleNames = garray.NewSortedStrArrayFrom(base_funs.RemoveSliceAt(userInfo.RoleNames, roleInfo.Name)).Unique().Slice()
   286  			}
   287  		}
   288  
   289  		return nil
   290  	})
   291  
   292  	return err == nil, err
   293  }
   294  
   295  // GetRoleMemberIds 获取角色下的所有用户ID
   296  func (s *sSysRole) GetRoleMemberIds(ctx context.Context, roleId int64, makeUserUnionMainId int64) ([]int64, error) {
   297  	roleInfo := sys_entity.SysRole{}
   298  	err := sys_dao.SysRole.Ctx(ctx).Where(sys_do.SysRole{Id: roleId}).Scan(&roleInfo)
   299  
   300  	if roleInfo.UnionMainId != makeUserUnionMainId {
   301  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "禁止跨商操作", sys_dao.SysRole.Table())
   302  	}
   303  
   304  	if err == sql.ErrNoRows {
   305  		return []int64{}, nil
   306  	}
   307  
   308  	if err != nil {
   309  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "角色ID错误", sys_dao.SysRole.Table())
   310  	}
   311  
   312  	if roleInfo.Id <= 0 {
   313  		return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, "查询角色ID信息不存在")
   314  	}
   315  
   316  	userIds, err := sys_service.Casbin().Enforcer().GetRoleManager().GetUsers(gconv.String(roleId), sys_consts.CasbinDomain)
   317  
   318  	if err != nil {
   319  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "用户ID错误", sys_dao.SysRole.Table())
   320  	}
   321  
   322  	return gconv.Int64s(userIds), nil
   323  }
   324  
   325  // GetRoleMemberList 获取角色下的所有用户
   326  func (s *sSysRole) GetRoleMemberList(ctx context.Context, roleId int64, makeUserUnionMainId int64) ([]*sys_model.SysUser, error) {
   327  	userIds, err := s.GetRoleMemberIds(ctx, roleId, makeUserUnionMainId)
   328  
   329  	userInfoArr := make([]*sys_model.SysUser, 0)
   330  
   331  	userList, err := sys_service.SysUser().QueryUserList(ctx, &base_model.SearchParams{
   332  		Filter: append(make([]base_model.FilterInfo, 0), base_model.FilterInfo{
   333  			Field:       sys_dao.SysUser.Columns().Id,
   334  			Where:       "in",
   335  			IsOrWhere:   false,
   336  			Value:       userIds,
   337  			IsNullValue: false,
   338  		}),
   339  	}, makeUserUnionMainId, true)
   340  
   341  	userInfoArr = userList.Records
   342  
   343  	if err != nil {
   344  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "查询用户信息失败", sys_dao.SysRole.Table())
   345  	}
   346  
   347  	result := make([]*sys_model.SysUser, 0)
   348  	// 移除密码信息
   349  	for _, user := range userInfoArr {
   350  		user.Password = ""
   351  		user.RoleNames = make([]string, 0)
   352  
   353  		roles, err := sys_service.SysRole().GetRoleListByUserId(ctx, user.Id)
   354  		if err == nil && len(roles) > 0 {
   355  			for _, role := range roles {
   356  				user.RoleNames = append(user.RoleNames, role.Name)
   357  			}
   358  		}
   359  		result = append(result, user)
   360  	}
   361  
   362  	return result, nil
   363  }
   364  
   365  // GetRoleListByUserId 获取用户拥有的所有角色
   366  func (s *sSysRole) GetRoleListByUserId(ctx context.Context, userId int64) ([]*sys_entity.SysRole, error) {
   367  
   368  	userInfo, err := sys_service.SysUser().GetSysUserById(ctx, userId)
   369  
   370  	if err != nil {
   371  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "用户ID错误", sys_dao.SysRole.Table())
   372  	}
   373  
   374  	if userInfo.Id <= 0 {
   375  		return nil, sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "查询用户ID信息不存在"), "", sys_dao.SysRole.Table())
   376  	}
   377  
   378  	roleIds, err := sys_service.Casbin().Enforcer().GetRoleManager().GetRoles(gconv.String(userId), sys_consts.CasbinDomain)
   379  
   380  	if err != nil {
   381  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "用户ID错误", sys_dao.SysRole.Table())
   382  	}
   383  
   384  	roleInfoArr := make([]*sys_entity.SysRole, 0)
   385  
   386  	err = sys_dao.SysRole.Ctx(ctx).WhereIn(sys_dao.SysRole.Columns().Id, roleIds).Scan(&roleInfoArr)
   387  
   388  	return roleInfoArr, nil
   389  }
   390  
   391  // SetRolePermissions 设置角色权限
   392  func (s *sSysRole) SetRolePermissions(ctx context.Context, roleId int64, permissionIds []int64, makeUserUnionMainId int64) (bool, error) {
   393  	roleInfo := sys_entity.SysRole{}
   394  	err := sys_dao.SysRole.Ctx(ctx).Where(sys_do.SysRole{Id: roleId}).Scan(&roleInfo)
   395  
   396  	// 判断是否跨商设置角色权限
   397  	if roleInfo.UnionMainId != makeUserUnionMainId {
   398  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "禁止跨商操作", sys_dao.SysRole.Table())
   399  	}
   400  
   401  	if err != nil {
   402  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "角色信息查询失败", sys_dao.SysRole.Table())
   403  	}
   404  
   405  	return sys_service.SysPermission().SetPermissionsByResource(ctx, gconv.String(roleId), permissionIds)
   406  }