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 }