github.com/SupenBysz/gf-admin-community@v0.7.4/internal/logic/sys_user/sys_user.go (about) 1 package user 2 3 import ( 4 "context" 5 "database/sql" 6 "errors" 7 "github.com/SupenBysz/gf-admin-community/sys_consts" 8 "github.com/SupenBysz/gf-admin-community/sys_model" 9 "github.com/SupenBysz/gf-admin-community/sys_model/sys_dao" 10 "github.com/SupenBysz/gf-admin-community/sys_model/sys_do" 11 "github.com/SupenBysz/gf-admin-community/sys_model/sys_entity" 12 "github.com/SupenBysz/gf-admin-community/sys_model/sys_enum" 13 "github.com/SupenBysz/gf-admin-community/sys_model/sys_hook" 14 "github.com/SupenBysz/gf-admin-community/sys_service" 15 "github.com/gogf/gf/v2/container/garray" 16 "github.com/gogf/gf/v2/database/gdb" 17 "github.com/gogf/gf/v2/errors/gcode" 18 "github.com/gogf/gf/v2/errors/gerror" 19 "github.com/gogf/gf/v2/frame/g" 20 "github.com/gogf/gf/v2/os/gtime" 21 "github.com/gogf/gf/v2/util/gconv" 22 "github.com/kysion/base-library/base_model" 23 "github.com/kysion/base-library/base_model/base_enum" 24 "github.com/kysion/base-library/utility/base_funs" 25 "github.com/kysion/base-library/utility/base_verify" 26 "github.com/kysion/base-library/utility/daoctl" 27 "github.com/kysion/base-library/utility/en_crypto" 28 "github.com/kysion/base-library/utility/kconv" 29 "github.com/kysion/base-library/utility/masker" 30 "github.com/yitter/idgenerator-go/idgen" 31 "math" 32 "sort" 33 "time" 34 ) 35 36 type hookInfo sys_model.KeyValueT[int64, sys_hook.UserHookInfo] 37 38 type sSysUser struct { 39 hookArr []hookInfo 40 //redisCache *gcache.Cache 41 Duration time.Duration 42 43 //// 密码加密 44 //CryptoPasswordFunc func(ctx context.Context, passwordStr string, user ...sys_entity.SysUser) (pwdEncode string) 45 } 46 47 func init() { 48 sys_service.RegisterSysUser(New()) 49 } 50 51 func New() *sSysUser { 52 return &sSysUser{ 53 //redisCache: gcache.New(), 54 hookArr: make([]hookInfo, 0), 55 } 56 } 57 58 // 59 //// 初始化缓存 60 //func (s *sSysUser) initInnerCacheItems(ctx context.Context) { 61 // size, _ := s.redisCache.Size(ctx) 62 // if size > 0 { 63 // return 64 // } 65 // 66 // items := daoctl.Scan[[]*sys_model.SysUser]( 67 // sys_dao.SysUser.Ctx(ctx). 68 // OrderDesc(sys_dao.SysUser.Columns().CreatedAt), 69 // ) 70 // 71 // s.redisCache.Clear(ctx) 72 // for _, sysUser := range *items { 73 // s.redisCache.Set(ctx, sysUser.Id, sysUser, s.Duration) 74 // } 75 //} 76 77 // InstallHook 安装Hook 78 func (s *sSysUser) InstallHook(event sys_enum.UserEvent, hookFunc sys_hook.UserHookFunc) int64 { 79 item := hookInfo{Key: idgen.NextId(), Value: sys_hook.UserHookInfo{Key: event, Value: hookFunc}} 80 s.hookArr = append(s.hookArr, item) 81 return item.Key 82 } 83 84 //// SetCryptoPasswordFunc 用于业务端自定义密码规则 85 //func (s *sSysUser) SetCryptoPasswordFunc(f func(ctx context.Context, passwordStr string, user ...sys_entity.SysUser) (pwdEncode string)) { 86 // s.CryptoPasswordFunc = f 87 //} 88 // 89 //// GetCryptoPasswordFunc 应用业务端自定义密码规则 90 //func (s *sSysUser) GetCryptoPasswordFunc() func(ctx context.Context, passwordStr string, user ...sys_entity.SysUser) (pwdEncode string) { 91 // return s.CryptoPasswordFunc 92 //} 93 94 // UnInstallHook 卸载Hook 95 func (s *sSysUser) UnInstallHook(savedHookId int64) { 96 newFuncArr := make([]hookInfo, 0) 97 for _, item := range s.hookArr { 98 if item.Key != savedHookId { 99 newFuncArr = append(newFuncArr, item) 100 continue 101 } 102 } 103 s.hookArr = newFuncArr 104 } 105 106 // CleanAllHook 清除所有Hook 107 func (s *sSysUser) CleanAllHook() { 108 s.hookArr = make([]hookInfo, 0) 109 } 110 111 // QueryUserList 获取用户列表 112 func (s *sSysUser) QueryUserList(ctx context.Context, info *base_model.SearchParams, unionMainId int64, isExport bool) (response *sys_model.SysUserListRes, err error) { 113 if info != nil { 114 newFields := make([]base_model.FilterInfo, 0) 115 116 // 移除类型筛选条件 117 for _, field := range info.Filter { 118 if field.Field != sys_dao.SysUser.Columns().Type { 119 newFields = append(newFields, field) 120 } 121 } 122 } 123 124 // 如果没有查询条件,则默认从缓存返回数据 125 if info != nil && len(info.Filter) <= 0 { 126 // 初始化内部缓存数据 127 //s.initInnerCacheItems(ctx) 128 129 response = &sys_model.SysUserListRes{} 130 if info.Pagination.PageSize <= 0 { 131 info.PageSize = 20 132 } 133 if info.Pagination.PageNum <= 0 { 134 info.PageSize = 1 135 } 136 137 // 如果缓存没有数据则直接返回 138 //size, _ := s.redisCache.Size(ctx) 139 userList, err := daoctl.Query[sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), nil, true) 140 if err != nil { 141 return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "用户列表查询失败", sys_dao.SysUser.Table()) 142 } 143 size := len(userList.Records) 144 145 if size <= 0 { 146 response.PaginationRes = base_model.PaginationRes{ 147 Pagination: info.Pagination, 148 PageTotal: 0, 149 Total: 0, 150 } 151 response.Records = []*sys_model.SysUser{} 152 } 153 154 // 设置分页信息 155 response.Pagination = info.Pagination 156 // 初始化分页统计信息 157 response.PaginationRes = base_model.PaginationRes{ 158 Pagination: info.Pagination, 159 PageTotal: gconv.Int(math.Ceil(gconv.Float64(size) / gconv.Float64(info.PageSize))), 160 Total: gconv.Int64(size), 161 } 162 beginRowIndex := info.PageNum*info.PageSize - info.PageSize 163 164 // 获得所有的key,遍历 165 result, err := daoctl.Query[*sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), info, isExport) 166 167 //keys, _ := s.redisCache.Keys(ctx) 168 169 for _, k := range result.Records { 170 if beginRowIndex > 0 { 171 beginRowIndex-- 172 } else if len(response.Records) < info.PageSize { 173 // 查询用户所拥有的角色 174 sysUser := &sys_model.SysUser{} 175 sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: gconv.String(k.Id)}).Scan(&sysUser) 176 177 _, err = s.getUserRole(ctx, sysUser, unionMainId) 178 if err != nil { 179 return nil, err 180 } 181 182 sysUser = s.masker(s.makeMore(ctx, sysUser)) 183 184 response.Records = append(response.Records, sysUser) 185 } 186 187 sort.Slice(response.Records, func(i, j int) bool { 188 return response.Records[i].CreatedAt.After(response.Records[j].CreatedAt) 189 }) 190 191 } 192 } 193 194 result, err := daoctl.Query[*sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), info, isExport) 195 196 newList := make([]*sys_model.SysUser, 0) 197 if result != nil && result.Records != nil && len(result.Records) > 0 { 198 for _, user := range result.Records { 199 user.RoleNames = make([]string, 0) 200 roleIds, err := sys_service.Casbin().Enforcer().GetRoleManager().GetRoles(gconv.String(user.Id), sys_consts.CasbinDomain) 201 202 if err != nil && err != sql.ErrNoRows { 203 return nil, err 204 } 205 206 if len(roleIds) > 0 { 207 roles, err := sys_service.SysRole().QueryRoleList(ctx, base_model.SearchParams{ 208 Filter: append(make([]base_model.FilterInfo, 0), base_model.FilterInfo{ 209 Field: sys_dao.SysRole.Columns().Id, 210 Where: "in", 211 IsOrWhere: false, 212 Value: roleIds, 213 }), 214 Pagination: base_model.Pagination{}, 215 }, unionMainId) 216 if err == nil && len(roles.Records) > 0 { 217 for _, role := range roles.Records { 218 user.RoleNames = append(user.RoleNames, role.Name) 219 } 220 } 221 } 222 user = s.masker(s.makeMore(ctx, user)) 223 newList = append(newList, user) 224 } 225 } 226 227 if newList != nil && len(newList) > 0 { 228 result.Records = newList 229 } 230 231 return (*sys_model.SysUserListRes)(result), err 232 } 233 234 // SetUserRoleIds 设置用户角色 235 func (s *sSysUser) SetUserRoleIds(ctx context.Context, roleIds []int64, userId int64) (bool, error) { 236 for _, roleId := range roleIds { 237 roleInfo := &sys_entity.SysRole{} 238 // 查找角色是否存在 239 roleInfo, err := sys_service.SysRole().GetRoleById(ctx, roleId) 240 241 if err != nil { 242 return false, sys_service.SysLogs().ErrorSimple(ctx, err, "角色ID错误", sys_dao.SysUser.Table()) 243 } 244 245 userInfo, err := sys_service.SysUser().GetSysUserById(ctx, userId) 246 247 if err != nil { 248 return false, sys_service.SysLogs().ErrorSimple(ctx, err, "用户ID错误", sys_dao.SysUser.Table()) 249 } 250 251 result, err := sys_service.Casbin().AddRoleForUserInDomain(gconv.String(userInfo.Id), gconv.String(roleInfo.Id), sys_consts.CasbinDomain) 252 253 if result == false || err != nil { 254 return result, sys_service.SysLogs().ErrorSimple(ctx, err, "设置用户角色失败", sys_dao.SysUser.Table()) 255 } 256 } 257 258 return true, nil 259 } 260 261 // CreateUser 创建用户 262 func (s *sSysUser) CreateUser(ctx context.Context, info sys_model.UserInnerRegister, userState sys_enum.UserState, userType sys_enum.UserType, customId ...int64) (*sys_model.SysUser, error) { 263 count, _ := sys_dao.SysUser.Ctx(ctx).Unscoped().Count(sys_dao.SysUser.Columns().Username, info.Username) 264 if count > 0 { 265 return nil, sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户名已经存在"), "", sys_dao.SysUser.Table()) 266 } 267 268 data := sys_model.SysUser{ 269 SysUser: &sys_entity.SysUser{ 270 Id: idgen.NextId(), 271 Username: info.Username, 272 Password: info.Password, 273 Mobile: info.Mobile, 274 Email: info.Email, 275 State: userState.Code(), 276 Type: userType.Code(), 277 CreatedAt: gtime.Now(), 278 }, 279 } 280 281 if len(customId) > 0 && customId[0] > 0 { 282 data.Id = customId[0] 283 } 284 pwdHash, err := en_crypto.PwdHash(info.Password, gconv.String(data.Id)) 285 286 // 业务层自定义密码加密规则 287 if sys_consts.Global.CryptoPasswordFunc != nil { 288 pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, info.Password, *data.SysUser) 289 } 290 291 // 密码赋值 292 data.Password = pwdHash 293 294 err = sys_dao.SysUser.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { 295 // 创建前 296 g.Try(ctx, func(ctx context.Context) { 297 for _, hook := range s.hookArr { 298 // 枚举优化使用:直接调用Has 299 //enumOb := sys_enum.User.Type.New(3, "") 300 //if enumOb.Has(sys_enum.User.Event.BeforeCreate) { // 单个满足 301 // 302 //} 303 //if hook.Value.Key.Has(sys_enum.User.Event.BeforeCreate, sys_enum.User.Event.AfterCreate) { // 多个满足 304 // 305 //} 306 307 // 自增 308 //enumOb.Add(sys_enum.User.Event.AfterCreate, sys_enum.User.Event.BeforeCreate) 309 310 // 自减少 311 //enumOb.Remove(sys_enum.User.Event.AfterCreate) 312 313 if (hook.Value.Key.Code() & sys_enum.User.Event.BeforeCreate.Code()) == sys_enum.User.Event.BeforeCreate.Code() { 314 res, _ := hook.Value.Value(ctx, sys_enum.User.Event.BeforeCreate, data) 315 res.Detail = &sys_entity.SysUserDetail{} 316 res.Detail.Id = data.Id 317 data.Detail = res.Detail 318 } 319 } 320 }) 321 322 { 323 _, err = sys_dao.SysUser.Ctx(ctx).OmitNilData().Data(data.SysUser).Insert() 324 325 if err != nil { 326 return sys_service.SysLogs().ErrorSimple(ctx, err, "账号注册失败", sys_dao.SysUser.Table()) 327 } 328 } 329 330 { 331 if data.Detail != nil && data.Detail.Id > 0 && (data.Detail.Realname != "" || data.Detail.UnionMainName != "") { 332 _, err = sys_dao.SysUserDetail.Ctx(ctx).OmitNilData().Data(data.Detail).Insert() 333 334 if err != nil { 335 return sys_service.SysLogs().ErrorSimple(ctx, err, "账号注册失败", sys_dao.SysUser.Table()) 336 } 337 } 338 339 /* 340 // if data.Detail != nil && data.Detail.Id > 0 && (data.Detail.Realname != "" || data.Detail.UnionMainName != "") { 341 342 _, err = sys_dao.SysUserDetail.Ctx(ctx).OmitNilData().Data(data.Detail).Insert() 343 344 if err != nil { 345 return sys_service.SysLogs().ErrorSimple(ctx, err, "账号注册失败", sys_dao.SysUser.Table()) 346 } 347 //} 348 */ 349 350 } 351 if len(info.RoleIds) > 0 { 352 ret, err := s.SetUserRoleIds(ctx, info.RoleIds, data.Id) 353 if ret != true || err != nil { 354 return sys_service.SysLogs().ErrorSimple(ctx, err, "角色设置失败!"+err.Error(), sys_dao.SysUser.Table()) 355 } 356 } 357 358 return nil 359 }) 360 361 if err != nil { 362 return nil, err 363 } 364 365 // 建后 366 g.Try(ctx, func(ctx context.Context) { 367 for _, hook := range s.hookArr { 368 if hook.Value.Key.Code()&sys_enum.User.Event.AfterCreate.Code() == sys_enum.User.Event.AfterCreate.Code() { 369 res, _ := hook.Value.Value(ctx, sys_enum.User.Event.AfterCreate, data) 370 res.Detail.Id = data.Id 371 data.Detail = res.Detail 372 } 373 } 374 }) 375 376 // 查询用户所拥有的角色 (指针传递) 377 s.getUserRole(ctx, &data) 378 379 // 增删改后不需要重新设置缓存,因为增伤缓存参数Duration为-1,就是删除缓存了 380 // s.redisCache.Set(ctx, data.Id, data, s.Duration) 381 382 return &data, nil 383 } 384 385 // SetUserPermissions 设置用户权限 386 func (s *sSysUser) SetUserPermissions(ctx context.Context, userId int64, permissionIds []int64) (bool, error) { 387 _, err := s.GetSysUserById(ctx, userId) 388 389 if err != nil { 390 return false, sys_service.SysLogs().ErrorSimple(ctx, err, "用户信息查询失败", sys_dao.SysRole.Table()) 391 } 392 393 return sys_service.SysPermission().SetPermissionsByResource(ctx, gconv.String(userId), permissionIds) 394 } 395 396 // GetSysUserByUsername 根据用户名获取用户 397 func (s *sSysUser) GetSysUserByUsername(ctx context.Context, username string) (response *sys_model.SysUser, err error) { 398 //s.initInnerCacheItems(ctx) 399 400 // 获取所有keys 401 // keys, err := s.redisCache.Keys(ctx) 402 userList, err := daoctl.Query[sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), nil, true) 403 404 user := &sys_model.SysUser{} 405 406 for _, k := range userList.Records { 407 //sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: gconv.String(k.Id)}).Scan(&user) 408 if k.Username == username { 409 sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: gconv.String(k.Id)}).Scan(&user) 410 response = s.masker(s.makeMore(ctx, user)) 411 // 查询用户所拥有的角色 (指针传递) 412 s.getUserRole(ctx, response) 413 return 414 } 415 } 416 417 if response == nil { 418 return nil, sys_service.SysLogs().ErrorSimple(ctx, sql.ErrNoRows, "用户信息不存在", sys_dao.SysUser.Table()) 419 } 420 421 response = s.masker(s.makeMore(ctx, response)) 422 return 423 } 424 425 // CheckPassword 检查密码是否正确 426 func (s *sSysUser) CheckPassword(ctx context.Context, userId int64, password string) (bool, error) { 427 //s.initInnerCacheItems(ctx) 428 429 userInfo, err := daoctl.GetByIdWithError[sys_entity.SysUser](sys_dao.SysUser.Ctx(ctx), userId) 430 431 if err != nil { 432 return false, sys_service.SysLogs().ErrorSimple(ctx, sql.ErrNoRows, "用户信息不存在", sys_dao.SysUser.Table()) 433 } 434 // if (){hook()} 435 // 取盐 436 salt := gconv.String(userId) 437 438 // 加密:用户输入的密码 + 他的id的后八位(盐) --进行Hash--> 用户提供的密文 439 pwdHash, err := en_crypto.PwdHash(password, salt) 440 // 业务层自定义密码加密规则 441 if sys_consts.Global.CryptoPasswordFunc != nil { 442 pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, password, *userInfo) 443 } 444 445 return userInfo.Password == pwdHash, err 446 } 447 448 // HasSysUserByUsername 判断用户名是否存在 449 func (s *sSysUser) HasSysUserByUsername(ctx context.Context, username string) bool { 450 data, _ := s.GetSysUserByUsername(ctx, username) 451 return data != nil 452 } 453 454 // GetSysUserById 根据用户ID获取用户信息 455 func (s *sSysUser) GetSysUserById(ctx context.Context, userId int64) (*sys_model.SysUser, error) { 456 //s.initInnerCacheItems(ctx) 457 458 user := sys_model.SysUser{} 459 err := sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{ 460 Id: userId, 461 }).Scan(&user) 462 463 if err != nil { 464 return nil, sys_service.SysLogs().ErrorSimple(ctx, sql.ErrNoRows, "用户信息不存在", sys_dao.SysUser.Table()) 465 } 466 467 // 查询用户所拥有的角色 (指针传递) 468 _, err = s.getUserRole(ctx, &user) 469 if err != nil { 470 return nil, err 471 } 472 473 return s.masker(s.makeMore(ctx, &user)), nil 474 } 475 476 func (s *sSysUser) MakeSession(ctx context.Context, userId int64) { 477 user, err := s.GetSysUserById(ctx, userId) 478 479 if err != nil { 480 return 481 } 482 483 token, err := sys_service.Jwt().GenerateToken(ctx, user) 484 if token != nil { 485 sys_service.Jwt().MakeSession(ctx, token.Token) 486 } 487 } 488 489 // SetUserPermissionIds 设置用户权限 490 func (s *sSysUser) SetUserPermissionIds(ctx context.Context, userId int64, permissionIds []int64) (bool, error) { 491 err := sys_dao.SysCasbin.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { 492 { 493 // 先清除roleId所有权限 494 _, err := sys_service.Casbin().DeletePermissionsForUser(gconv.String(userId)) 495 496 if len(permissionIds) <= 0 { 497 return err 498 } 499 } 500 501 // 重新赋予roleId新的权限清单 502 for _, item := range permissionIds { 503 ret, err := sys_service.Casbin().Enforcer().AddPermissionForUser(gconv.String(userId), sys_consts.CasbinDomain, gconv.String(item), "allow") 504 if err != nil || ret == false { 505 return err 506 } 507 } 508 return nil 509 }) 510 if err != nil { 511 return false, sys_service.SysLogs().ErrorSimple(ctx, err, "设置用户权限失败", sys_dao.SysUser.Table()) 512 } 513 514 return true, nil 515 } 516 517 // DeleteUser 删除用户信息,该方法一般由后端业务层内部调用 518 func (s *sSysUser) DeleteUser(ctx context.Context, id int64) (bool, error) { 519 _, err := s.GetSysUserById(ctx, id) 520 if err != nil { 521 return false, err 522 } 523 524 err = sys_dao.SysUser.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { 525 // 移除员工权限 526 _, err = sys_service.SysPermission().SetPermissionsByResource(ctx, gconv.String(id), []int64{0}) 527 if err != nil && err != sql.ErrNoRows { 528 return err 529 } 530 531 // 移除员工角色 532 sys_service.SysUser().SetUserRoleIds(ctx, []int64{0}, id) 533 if err != nil { 534 return err 535 } 536 537 // 删除用户附加信息 538 _, err = sys_dao.SysUserDetail.Ctx(ctx).Unscoped().Delete(sys_do.SysUserDetail{Id: id}) 539 if err != nil && err != sql.ErrNoRows { 540 return err 541 } 542 543 // 删除用户 544 _, err = sys_dao.SysUser.Ctx(ctx).Unscoped().Delete(sys_do.SysUser{Id: id}) 545 if err != nil && err != sql.ErrNoRows { 546 return err 547 } 548 549 return nil 550 }) 551 552 if err != nil { 553 return false, sys_service.SysLogs().ErrorSimple(ctx, err, "删除员工信息失败", sys_dao.SysUser.Table()) 554 } 555 556 // daoctl.RemoveQueryCache(sys_dao.SysUser.DB(), sys_dao.SysUser.Table()) 557 558 return true, nil 559 } 560 561 // SetUsername 修改自己的账号登陆名称 562 func (s *sSysUser) SetUsername(ctx context.Context, newUsername string, userId int64) (bool, error) { 563 result, err := sys_dao.SysUser.Ctx(ctx).Data(sys_do.SysUser{Username: newUsername}).Where(sys_do.SysUser{Id: userId}).Update() 564 565 if err != nil || result == nil { 566 return false, err 567 } 568 569 return true, nil 570 } 571 572 // SetUserState 设置用户状态 573 func (s *sSysUser) SetUserState(ctx context.Context, userId int64, state sys_enum.UserType) (bool, error) { 574 sys_dao.SysUser.DB().Tables(ctx) 575 result, err := sys_dao.SysUser.Ctx(ctx).Data(sys_do.SysUser{State: state.Code()}).Where(sys_do.SysUser{Id: userId}).Update() 576 577 sys_dao.SysUser.Table() 578 579 if err != nil || result == nil { 580 return false, err 581 } 582 583 return true, nil 584 } 585 586 // UpdateUserPassword 修改用户登录密码 587 func (s *sSysUser) UpdateUserPassword(ctx context.Context, info sys_model.UpdateUserPassword, userId int64) (bool, error) { 588 // 查询到用户信息 不能使用这个操作去查询用户,因为masker操作会把用户密码变空 589 // sysUserInfo, err := sys_service.SysUser().GetSysUserById(ctx, userId) 590 591 sysUserInfo, err := daoctl.GetByIdWithError[sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), userId) 592 593 if err != nil { 594 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户不存在") 595 } 596 597 // 判断输入的两次密码是否相同 598 if info.Password != info.ConfirmPassword { 599 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "两次输入的密码不一致,修改失败") 600 } 601 602 { 603 // 传入用户输入的原始密码,进行hash,看是否和数据库中原始密码一致 604 hash1, _ := en_crypto.PwdHash(info.OldPassword, gconv.String(sysUserInfo.Id)) 605 // 业务层自定义密码加密规则 606 if sys_consts.Global.CryptoPasswordFunc != nil { 607 hash1 = sys_consts.Global.CryptoPasswordFunc(ctx, info.OldPassword, *sysUserInfo.SysUser) 608 } 609 if sysUserInfo.Password != hash1 { 610 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "原密码输入错误,修改失败") 611 } 612 } 613 614 { 615 // 处理hook订阅 616 g.Try(ctx, func(ctx context.Context) { 617 for _, hook := range s.hookArr { 618 if hook.Value.Key.Code()&sys_enum.User.Event.ChangePassword.Code() == sys_enum.User.Event.ChangePassword.Code() { 619 // 调用hook 620 _, err = hook.Value.Value(ctx, sys_enum.User.Event.ChangePassword, *sysUserInfo) 621 if err != nil { 622 break 623 } 624 } 625 } 626 }) 627 if err != nil { 628 return false, err 629 } 630 } 631 632 pwdHash, err := en_crypto.PwdHash(info.Password, gconv.String(sysUserInfo.Id)) 633 // 业务层自定义密码加密规则 634 if sys_consts.Global.CryptoPasswordFunc != nil { 635 pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, info.Password, *sysUserInfo.SysUser) 636 } 637 638 _, err = sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: sysUserInfo.Id}).Update(sys_do.SysUser{Password: pwdHash}) 639 640 if err != nil { 641 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "密码修改失败") 642 } 643 644 return true, nil 645 } 646 647 // ResetUserPassword 重置用户密码 (超级管理员无需验证验证,XX商管理员重置员工密码无需验证) 648 func (s *sSysUser) ResetUserPassword(ctx context.Context, userId int64, password string, confirmPassword string) (bool, error) { 649 // hook判断当前登录身份是否可以重置密码 650 user, err := s.GetSysUserById(ctx, userId) 651 { 652 //s.initInnerCacheItems(ctx) 653 654 if err != nil { 655 return false, err 656 } 657 658 // 发布广播 659 g.Try(ctx, func(ctx context.Context) { 660 for _, hook := range s.hookArr { 661 if hook.Value.Key.Code()&sys_enum.User.Event.ResetPassword.Code() == sys_enum.User.Event.ResetPassword.Code() { 662 _, err = hook.Value.Value(ctx, sys_enum.User.Event.ResetPassword, *kconv.Struct(user, &sys_model.SysUser{})) 663 if err != nil { 664 break 665 } 666 } 667 } 668 }) 669 670 if err != nil { 671 return false, err 672 } 673 } 674 675 // 生成密码,重置密码 676 { 677 if password != confirmPassword { 678 return false, gerror.NewCode(gcode.CodeValidationFailed, "两次密码不一致,请重新输入") 679 } 680 // 取盐 681 salt := gconv.String(userId) 682 683 // 加密 684 pwdHash, _ := en_crypto.PwdHash(password, salt) 685 // 业务层自定义密码加密规则 686 if sys_consts.Global.CryptoPasswordFunc != nil { 687 pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, password, *user.SysUser) 688 } 689 690 result, err := sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: userId}).Update(sys_do.SysUser{Password: pwdHash}) 691 692 // 受影响的行数 693 count, _ := result.RowsAffected() 694 695 if err != nil || count != 1 { 696 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "重置密码失败") 697 } 698 } 699 700 return true, nil 701 } 702 703 // HasSysUserEmail 邮箱是否存在 704 func (s *sSysUser) HasSysUserEmail(ctx context.Context, email string) bool { 705 response, _ := s.GetSysUserByEmail(ctx, email) 706 707 return response != nil 708 } 709 710 // GetSysUserByEmail 根据邮箱获取用户信息 711 func (s *sSysUser) GetSysUserByEmail(ctx context.Context, email string) (response *sys_model.SysUser, err error) { 712 713 err = sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Email: email}).Scan(response) 714 715 return 716 } 717 718 // ResetUserEmail 重置用户邮箱 719 func (s *sSysUser) ResetUserEmail(ctx context.Context, userId int64, email string) (bool, error) { 720 // hook判断当前登录身份是否可以重置密码 721 user, err := s.GetSysUserById(ctx, userId) 722 { 723 //s.initInnerCacheItems(ctx) 724 725 if err != nil { 726 return false, err 727 } 728 729 // 发布广播 730 err = g.Try(ctx, func(ctx context.Context) { 731 for _, hook := range s.hookArr { 732 if hook.Value.Key.Code()&sys_enum.User.Event.ResetEmail.Code() == sys_enum.User.Event.ResetEmail.Code() { 733 _, err = hook.Value.Value(ctx, sys_enum.User.Event.ResetEmail, *kconv.Struct(user, &sys_model.SysUser{})) 734 if err != nil { 735 break 736 } 737 } 738 } 739 }) 740 741 if err != nil { 742 return false, err 743 } 744 } 745 746 affected, err := daoctl.UpdateWithError(sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: userId}), sys_do.SysUser{Email: email}) 747 748 return affected > 0, err 749 } 750 751 // SetUserRoles 设置用户角色 752 func (s *sSysUser) SetUserRoles(ctx context.Context, userId int64, roleIds []int64, makeUserUnionMainId int64) (bool, error) { 753 data, err := s.GetSysUserById(ctx, userId) 754 if err != nil { 755 return false, err 756 } 757 758 err = sys_dao.SysRole.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { 759 for _, roleId := range roleIds { 760 roleInfo, err := sys_service.SysRole().GetRoleById(ctx, roleId) 761 762 if err != nil { 763 return sys_service.SysLogs().ErrorSimple(ctx, err, "角色ID错误", sys_dao.SysRole.Table()) 764 } 765 766 if roleInfo.UnionMainId != makeUserUnionMainId { 767 return sys_service.SysLogs().ErrorSimple(ctx, err, roleInfo.Name+" 角色信息校验失败", sys_dao.SysRole.Table()) 768 } 769 770 ret, _ := sys_service.Casbin().AddRoleForUserInDomain(gconv.String(userId), gconv.String(roleInfo.Id), sys_consts.CasbinDomain) 771 if ret == true { 772 // 重置用户角色名称,并自动去重 773 data.RoleNames = garray.NewSortedStrArrayFrom(append(data.RoleNames, roleInfo.Name)).Unique().Slice() 774 } 775 } 776 return nil 777 }) 778 return err == nil, err 779 } 780 781 // UpdateUserExDetail 更新用户扩展信息 782 func (s *sSysUser) UpdateUserExDetail(ctx context.Context, user *sys_model.SysUser) (*sys_model.SysUser, error) { 783 //s.initInnerCacheItems(ctx) 784 785 var data *sys_entity.SysUserDetail 786 787 err := sys_dao.SysUserDetail.Ctx(ctx).Where(sys_do.SysUserDetail{Id: user.Id}).Scan(&data) 788 if err != nil && !errors.Is(err, sql.ErrNoRows) { 789 return nil, err 790 } 791 792 if user.Detail == nil { 793 if data != nil { 794 user.Detail = data 795 } else { 796 user.Detail = &sys_entity.SysUserDetail{ 797 Id: user.Id, 798 Realname: "", 799 UnionMainName: "", 800 LastLoginIp: "", 801 LastLoginArea: "", 802 LastLoginAt: nil, 803 } 804 } 805 } 806 807 if err == nil && data == nil || errors.Is(err, sql.ErrNoRows) { 808 _, err = sys_dao.SysUserDetail.Ctx(ctx).Insert(user.Detail) 809 if err != nil { 810 return nil, err 811 } 812 } else { 813 if data == nil { 814 _, err = sys_dao.SysUserDetail.Ctx(ctx).Data(sys_do.SysUserDetail{ 815 Realname: user.Detail.Realname, 816 UnionMainName: user.Detail.UnionMainName, 817 LastLoginIp: user.Detail.LastLoginIp, 818 LastLoginArea: user.Detail.LastLoginArea, 819 LastLoginAt: user.Detail.LastLoginAt, 820 }).Where(sys_do.SysUserDetail{Id: user.Id}).Update() 821 if err != nil { 822 return nil, err 823 } 824 } 825 } 826 827 //s.redisCache.Set(ctx, user.Id, user, s.Duration) 828 return user, nil 829 } 830 831 // GetUserDetail 查看用户详情,含完整手机号 832 func (s *sSysUser) GetUserDetail(ctx context.Context, userId int64) (*sys_model.SysUser, error) { 833 //s.initInnerCacheItems(ctx) 834 835 // Ctx()里面包含对所有Cache操作的赋值,查询不需要写Cache 836 user := sys_model.SysUser{} 837 err := sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{ 838 Id: userId, 839 }).Scan(&user) 840 841 if err != nil { 842 return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户信息不存在") 843 } 844 845 user.Password = masker.MaskString(user.Password, masker.Password) 846 847 // 查询用户所拥有的角色 (指针传递) 848 _, err = s.getUserRole(ctx, &user) 849 if err != nil { 850 return nil, err 851 } 852 853 return s.makeMore(ctx, &user), nil 854 } 855 856 // GetUserListByMobileOrMail 根据手机号或者邮箱查询用户列表 857 func (s *sSysUser) GetUserListByMobileOrMail(ctx context.Context, info string) (*sys_model.SysUserListRes, error) { 858 userModel := sys_dao.SysUser.Ctx(ctx) 859 if base_verify.IsPhone(info) { 860 userModel = userModel.Where(sys_do.SysUser{Mobile: info}) 861 } else if base_verify.IsEmail(info) { 862 userModel = userModel.Where(sys_do.SysUser{Email: info}) 863 } 864 865 userList, err := daoctl.Query[*sys_model.SysUser](userModel, nil, false) 866 867 if err != nil { 868 return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户信息不存在") 869 } 870 871 newList := make([]*sys_model.SysUser, 0) 872 for _, user := range userList.Records { 873 uData := kconv.Struct(user, &sys_model.SysUser{}) 874 uInfo := s.masker(s.makeMore(ctx, uData)) 875 newList = append(newList, uInfo) 876 } 877 878 if newList != nil { 879 userList.Records = newList 880 } 881 882 return (*sys_model.SysUserListRes)(userList), nil 883 } 884 885 // SetUserMobile 设置用户手机号 886 func (s *sSysUser) SetUserMobile(ctx context.Context, newMobile, captcha, password string, userId int64) (bool, error) { 887 //s.initInnerCacheItems(ctx) 888 889 _, err := sys_service.SysSms().Verify(ctx, newMobile, captcha, base_enum.Captcha.Type.SetMobile) 890 if err != nil { 891 return false, err 892 } 893 894 userInfo := sys_model.SysUser{} 895 sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{ 896 Id: userId, 897 }).Scan(&userInfo) 898 899 if err != nil { 900 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户信息不存在") 901 } 902 if newMobile == userInfo.Mobile { 903 return true, nil 904 } 905 906 // 检验密码 907 user, err := daoctl.GetByIdWithError[sys_entity.SysUser](sys_dao.SysUser.Ctx(ctx), userInfo.Id) 908 909 pwdHash, err := en_crypto.PwdHash(password, gconv.String(userId)) 910 911 // 业务层自定义密码加密规则 912 if sys_consts.Global.CryptoPasswordFunc != nil { 913 pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, password, *userInfo.SysUser) 914 } 915 916 if pwdHash != user.Password { 917 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "登录密码错误") 918 } 919 920 affected, err := daoctl.UpdateWithError(sys_dao.SysUser.Ctx(ctx).Data(sys_do.SysUser{Mobile: newMobile, UpdatedAt: gtime.Now()}).Where(sys_do.SysUser{ 921 Id: userId, 922 })) 923 924 if err != nil || affected == 0 { 925 return false, sys_service.SysLogs().ErrorSimple(ctx, err, "设置用户手机号失败", sys_dao.SysUser.Table()) 926 } 927 928 // 清除redis验证码缓存 929 //key := sys_enum.Sms.CaptchaType.SetMobile.Description() + "_" + newMobile 930 //g.DB().GetCache().Remove(ctx, key) 931 932 return true, nil 933 } 934 935 // SetUserMail 设置用户邮箱 936 func (s *sSysUser) SetUserMail(ctx context.Context, oldMail, newMail, captcha, password string, userId int64) (bool, error) { 937 //s.initInnerCacheItems(ctx) 938 939 _, err := sys_service.SysMails().Verify(ctx, newMail, captcha, base_enum.Captcha.Type.SetMail) 940 if err != nil { 941 return false, err 942 } 943 944 mailUser := sys_entity.SysUser{} 945 err = sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: userId, Email: oldMail}).Scan(&mailUser) 946 if err != nil { 947 return false, sys_service.SysLogs().ErrorSimple(ctx, err, "原邮箱错误", sys_dao.SysUser.Table()) 948 } 949 950 userInfo := sys_model.SysUser{} 951 sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{ 952 Id: userId, 953 }).Scan(&userInfo) 954 955 if err != nil { 956 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户信息不存在") 957 } 958 if newMail == userInfo.Email { 959 return true, nil 960 } 961 962 // 检验密码 963 user, err := daoctl.GetByIdWithError[sys_entity.SysUser](sys_dao.SysUser.Ctx(ctx), userInfo.Id) 964 965 pwdHash, err := en_crypto.PwdHash(password, gconv.String(userId)) 966 967 // 业务层自定义密码加密规则 968 if sys_consts.Global.CryptoPasswordFunc != nil { 969 pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, password, *userInfo.SysUser) 970 } 971 972 if pwdHash != user.Password { 973 return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "登录密码错误") 974 } 975 976 affected, err := daoctl.UpdateWithError(sys_dao.SysUser.Ctx(ctx).Data(sys_do.SysUser{Email: newMail, UpdatedAt: gtime.Now()}).Where(sys_do.SysUser{ 977 Id: userId, 978 })) 979 980 if err != nil || affected == 0 { 981 return false, sys_service.SysLogs().ErrorSimple(ctx, err, "设置用户邮箱失败", sys_dao.SysUser.Table()) 982 } 983 984 return true, nil 985 } 986 987 func (s *sSysUser) getUserRole(ctx context.Context, sysUser *sys_model.SysUser, unionMainId ...int64) (*sys_model.SysUser, error) { 988 989 if unionMainId == nil || len(unionMainId) <= 0 || unionMainId[0] == 0 { 990 getS := sys_service.SysSession().Get(ctx) 991 if getS != nil { 992 sessionUser := getS.JwtClaimsUser 993 if sessionUser != nil { 994 unionMainId = make([]int64, 1) 995 unionMainId[0] = sessionUser.UnionMainId 996 } 997 } 998 999 } 1000 1001 roleIds, _ := sys_service.Casbin().Enforcer().GetRoleManager().GetRoles(gconv.String(sysUser.Id), sys_consts.CasbinDomain) 1002 1003 sysUser.RoleNames = []string{} 1004 1005 // 如果有角色信息则加载角色信息 1006 if len(roleIds) > 0 { 1007 var unionMainIdInfo int64 = 0 1008 if len(unionMainId) > 0 { 1009 unionMainIdInfo = unionMainId[0] 1010 } 1011 roles, err := sys_service.SysRole().QueryRoleList(ctx, base_model.SearchParams{ 1012 Filter: append(make([]base_model.FilterInfo, 0), base_model.FilterInfo{ 1013 Field: sys_dao.SysRole.Columns().Id, 1014 Where: "in", 1015 IsOrWhere: false, 1016 Value: roleIds, 1017 }), 1018 Pagination: base_model.Pagination{}, 1019 }, unionMainIdInfo) 1020 if err == nil && len(roles.Records) > 0 { 1021 for _, role := range roles.Records { 1022 sysUser.RoleNames = append(sysUser.RoleNames, role.Name) 1023 } 1024 } 1025 } 1026 1027 return sysUser, nil 1028 } 1029 1030 func (s *sSysUser) masker(user *sys_model.SysUser) *sys_model.SysUser { 1031 user.Password = masker.MaskString(user.Password, masker.Password) 1032 user.Mobile = masker.MaskString(user.Mobile, masker.MaskPhone) 1033 return user 1034 } 1035 1036 // makeMore 处理订阅请求,获取订阅数据回调返回 1037 func (s *sSysUser) makeMore(ctx context.Context, data *sys_model.SysUser) *sys_model.SysUser { 1038 base_funs.AttrMake[sys_model.SysUser](ctx, 1039 sys_dao.SysUser.Columns().Id, 1040 func() *sys_entity.SysUserDetail { 1041 1042 //result, _ := daoctl.GetByIdWithError[sys_entity.SysUserDetail](sys_dao.SysUserDetail.Ctx(ctx), data.Id) 1043 resultArr, _ := daoctl.Query[sys_entity.SysUserDetail](sys_dao.SysUserDetail.Ctx(ctx), nil, true) 1044 //result, _ := daoctl.ScanWithError[sys_entity.SysUserDetail](sys_dao.SysUserDetail.Ctx(ctx).Where(sys_do.SysUserDetail{Id: data.Id})) 1045 var result *sys_entity.SysUserDetail 1046 for _, record := range resultArr.Records { 1047 if record.Id == data.Id { 1048 result = &record 1049 break 1050 } 1051 } 1052 if result == nil { 1053 return nil 1054 } 1055 res := kconv.Struct[sys_entity.SysUserDetail](ctx, *result) 1056 if res.LastLoginIp == "" { 1057 return nil 1058 } 1059 data.Detail = &res 1060 return data.Detail 1061 }, 1062 ) 1063 return data 1064 }