// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! namespace Admin.NET.Core.Service; /// /// 系统用户服务 🧩 /// [ApiDescriptionSettings(Order = 490)] public class SysUserService : IDynamicApiController, ITransient { private readonly UserManager _userManager; private readonly SysOrgService _sysOrgService; private readonly SysUserExtOrgService _sysUserExtOrgService; private readonly SysUserRoleService _sysUserRoleService; private readonly SysConfigService _sysConfigService; private readonly SysOnlineUserService _sysOnlineUserService; private readonly SysUserMenuService _sysUserMenuService; private readonly SysCacheService _sysCacheService; private readonly SysUserLdapService _sysUserLdapService; private readonly SqlSugarRepository _sysUserRep; private readonly IEventPublisher _eventPublisher; public SysUserService(UserManager userManager, SysOrgService sysOrgService, SysUserExtOrgService sysUserExtOrgService, SysUserRoleService sysUserRoleService, SysConfigService sysConfigService, SysOnlineUserService sysOnlineUserService, SysCacheService sysCacheService, SysUserLdapService sysUserLdapService, SqlSugarRepository sysUserRep, SysUserMenuService sysUserMenuService, IEventPublisher eventPublisher) { _userManager = userManager; _sysOrgService = sysOrgService; _sysUserExtOrgService = sysUserExtOrgService; _sysUserRoleService = sysUserRoleService; _sysConfigService = sysConfigService; _sysOnlineUserService = sysOnlineUserService; _sysCacheService = sysCacheService; _sysUserLdapService = sysUserLdapService; _sysUserMenuService = sysUserMenuService; _sysUserRep = sysUserRep; _eventPublisher = eventPublisher; } /// /// 获取用户分页列表 🔖 /// /// /// [DisplayName("获取用户分页列表")] public virtual async Task> Page(PageUserInput input) { //获取子节点Id集合(包含自己) var orgList = await _sysOrgService.GetChildIdListWithSelfById(input.OrgId); return await _sysUserRep.AsQueryable() .LeftJoin((u, a) => u.OrgId == a.Id) .LeftJoin((u, a, b) => u.PosId == b.Id) .Where(u => u.AccountType != AccountTypeEnum.SuperAdmin) .WhereIF(input.OrgId > 0, u => orgList.Contains(u.OrgId)) .WhereIF(!_userManager.SuperAdmin, u => u.AccountType != AccountTypeEnum.SysAdmin) .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId) .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account.Contains(input.Account)) .WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName)) .WhereIF(!string.IsNullOrWhiteSpace(input.PosName), (u, a, b) => b.Name.Contains(input.PosName)) .WhereIF(!string.IsNullOrWhiteSpace(input.Phone), u => u.Phone.Contains(input.Phone)) .OrderBy(u => new { u.OrderNo, u.Id }) .Select((u, a, b) => new UserOutput { OrgName = a.Name, PosName = b.Name, RoleName = SqlFunc.Subqueryable().LeftJoin((m, n) => m.RoleId == n.Id).Where(m => m.UserId == u.Id).SelectStringJoin((m, n) => n.Name, ","), DomainAccount = SqlFunc.Subqueryable().Where(m => m.UserId == u.Id).Select(m => m.Account) }, true) .ToPagedListAsync(input.Page, input.PageSize); } /// /// 增加用户 🔖 /// /// /// [UnitOfWork] [ApiDescriptionSettings(Name = "Add"), HttpPost] [DisplayName("增加用户")] public virtual async Task AddUser(AddUserInput input) { var isExist = await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Account == input.Account); if (isExist) throw Oops.Oh(ErrorCodeEnum.D1003); if (!string.IsNullOrWhiteSpace(input.Phone) && await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032); // 禁止越权新增超级管理员和系统管理员 if (_userManager.AccountType != AccountTypeEnum.SuperAdmin && input.AccountType is AccountTypeEnum.SuperAdmin or AccountTypeEnum.SysAdmin) throw Oops.Oh(ErrorCodeEnum.D1038); var password = await _sysConfigService.GetConfigValue(ConfigConst.SysPassword); var user = input.Adapt(); user.Password = CryptogramUtil.Encrypt(password); var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync(); input.Id = newUser.Id; await UpdateRoleAndExtOrg(input); // 增加域账号 if (!string.IsNullOrWhiteSpace(input.DomainAccount)) await _sysUserLdapService.AddUserLdap(newUser.TenantId!.Value, newUser.Id, newUser.Account, input.DomainAccount); // 发布系统用户操作事件 await _eventPublisher.PublishAsync(SysUserEventTypeEnum.Add, new { Entity = newUser, Input = input }); return newUser.Id; } /// /// 注册用户 🔖 /// /// /// [NonAction] public virtual async Task RegisterUser(AddUserInput input) { var isExist = await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Account == input.Account); if (isExist) throw Oops.Oh(ErrorCodeEnum.D1003); if (!string.IsNullOrWhiteSpace(input.Phone) && await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032); // 禁止越权注册 if (input.AccountType is AccountTypeEnum.SuperAdmin or AccountTypeEnum.SysAdmin) throw Oops.Oh(ErrorCodeEnum.D1038); if (string.IsNullOrWhiteSpace(input.Password)) { var password = await _sysConfigService.GetConfigValue(ConfigConst.SysPassword); input.Password = CryptogramUtil.Encrypt(password); } var user = input.Adapt(); var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync(); input.Id = newUser.Id; await UpdateRoleAndExtOrg(input); // 增加域账号 if (!string.IsNullOrWhiteSpace(input.DomainAccount)) await _sysUserLdapService.AddUserLdap(newUser.TenantId!.Value, newUser.Id, newUser.Account, input.DomainAccount); // 发布系统用户操作事件 await _eventPublisher.PublishAsync(SysUserEventTypeEnum.Register, new { Entity = newUser, Input = input }); return newUser.Id; } /// /// 更新用户 🔖 /// /// /// [UnitOfWork] [ApiDescriptionSettings(Name = "Update"), HttpPost] [DisplayName("更新用户")] public virtual async Task UpdateUser(UpdateUserInput input) { if (await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Account == input.Account && u.Id != input.Id)) throw Oops.Oh(ErrorCodeEnum.D1003); if (!string.IsNullOrWhiteSpace(input.Phone) && await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Phone == input.Phone && u.Id != input.Id)) throw Oops.Oh(ErrorCodeEnum.D1032); // 禁止越权更新超级管理员或系统管理员信息 if (_userManager.AccountType != AccountTypeEnum.SuperAdmin && input.AccountType is AccountTypeEnum.SuperAdmin or AccountTypeEnum.SysAdmin) throw Oops.Oh(ErrorCodeEnum.D1038); await _sysUserRep.AsUpdateable(input.Adapt()).IgnoreColumns(true) .IgnoreColumns(u => new { u.Password, u.Status, u.TenantId }).ExecuteCommandAsync(); await UpdateRoleAndExtOrg(input); // 删除用户机构缓存 SqlSugarFilter.DeleteUserOrgCache(input.Id, _sysUserRep.Context.CurrentConnectionConfig.ConfigId.ToString()); // 若账号的角色和组织架构发生变化,则强制下线账号进行权限更新 var user = await _sysUserRep.AsQueryable().ClearFilter().FirstAsync(u => u.Id == input.Id); var roleIds = await GetOwnRoleList(input.Id); if (input.OrgId != user.OrgId || !input.RoleIdList.OrderBy(u => u).SequenceEqual(roleIds.OrderBy(u => u))) await _sysOnlineUserService.ForceOffline(input.Id); // 更新域账号 await _sysUserLdapService.AddUserLdap(user.TenantId!.Value, user.Id, user.Account, input.DomainAccount); // 发布系统用户操作事件 await _eventPublisher.PublishAsync(SysUserEventTypeEnum.Update, new { Entity = user, Input = input }); } /// /// 更新角色和扩展机构 /// /// /// private async Task UpdateRoleAndExtOrg(AddUserInput input) { await GrantRole(new UserRoleInput { UserId = input.Id, RoleIdList = input.RoleIdList }); await _sysUserExtOrgService.UpdateUserExtOrg(input.Id, input.ExtOrgIdList); } /// /// 删除用户 🔖 /// /// /// [UnitOfWork] [ApiDescriptionSettings(Name = "Delete"), HttpPost] [DisplayName("删除用户")] public virtual async Task DeleteUser(DeleteUserInput input) { var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009); user.ValidateIsSuperAdminAccountType(); user.ValidateIsUserId(_userManager.UserId); // 若账号为租户默认账号则禁止删除 var isTenantUser = await _sysUserRep.ChangeRepository>().IsAnyAsync(u => u.UserId == input.Id); if (isTenantUser) throw Oops.Oh(ErrorCodeEnum.D1029); // 若账号为开放接口绑定账号则禁止删除 var isOpenAccessUser = await _sysUserRep.ChangeRepository>().IsAnyAsync(u => u.BindUserId == input.Id); if (isOpenAccessUser) throw Oops.Oh(ErrorCodeEnum.D1030); // 强制下线 await _sysOnlineUserService.ForceOffline(user.Id); await _sysUserRep.DeleteAsync(user); // 删除用户角色 await _sysUserRoleService.DeleteUserRoleByUserId(input.Id); // 删除用户扩展机构 await _sysUserExtOrgService.DeleteUserExtOrgByUserId(input.Id); // 删除域账号 await _sysUserLdapService.DeleteUserLdapByUserId(input.Id); // 删除用户收藏菜单 await _sysUserMenuService.DeleteUserMenuList(input.Id); // 发布系统用户操作事件 await _eventPublisher.PublishAsync(SysUserEventTypeEnum.Delete, new { Entity = user, Input = input }); } /// /// 查看用户基本信息 🔖 /// /// [DisplayName("查看用户基本信息")] public virtual async Task GetBaseInfo() { return await _sysUserRep.GetByIdAsync(_userManager.UserId); } /// /// 更新用户基本信息 🔖 /// /// [ApiDescriptionSettings(Name = "BaseInfo"), HttpPost] [DisplayName("更新用户基本信息")] public virtual async Task UpdateBaseInfo(SysUser user) { return await _sysUserRep.AsUpdateable(user) .IgnoreColumns(u => new { u.CreateTime, u.Account, u.Password, u.AccountType, u.OrgId, u.PosId }).ExecuteCommandAsync(); } /// /// 设置用户状态 🔖 /// /// /// [UnitOfWork] [DisplayName("设置用户状态")] public virtual async Task SetStatus(UserInput input) { if (_userManager.UserId == input.Id) throw Oops.Oh(ErrorCodeEnum.D1026); var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009); user.ValidateIsSuperAdminAccountType(ErrorCodeEnum.D1015); if (!Enum.IsDefined(typeof(StatusEnum), input.Status)) throw Oops.Oh(ErrorCodeEnum.D3005); // 账号禁用则增加黑名单,账号启用则移除黑名单 var sysCacheService = App.GetRequiredService(); if (input.Status == StatusEnum.Disable) { sysCacheService.Set($"{CacheConst.KeyBlacklist}{user.Id}", $"{user.RealName}-{user.Phone}"); // 强制下线 await _sysOnlineUserService.ForceOffline(user.Id); } else { sysCacheService.Remove($"{CacheConst.KeyBlacklist}{user.Id}"); } user.Status = input.Status; var rows = await _sysUserRep.AsUpdateable(user).UpdateColumns(u => new { u.Status }).ExecuteCommandAsync(); // 发布系统用户操作事件 if (rows > 0) await _eventPublisher.PublishAsync(SysUserEventTypeEnum.SetStatus, new { Entity = user, Input = input }); return rows; } /// /// 授权用户角色 🔖 /// /// /// [UnitOfWork] [DisplayName("授权用户角色")] public async Task GrantRole(UserRoleInput input) { //var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D0009); //if (user.AccountType == AccountTypeEnum.SuperAdmin) // throw Oops.Oh(ErrorCodeEnum.D1022); await _sysUserRoleService.GrantUserRole(input); // 发布系统用户操作事件 await _eventPublisher.PublishAsync(SysUserEventTypeEnum.UpdateRole, input); } /// /// 修改用户密码 🔖 /// /// /// [DisplayName("修改用户密码")] public virtual async Task ChangePwd(ChangePwdInput input) { // 国密SM2解密(前端密码传输SM2加密后的) input.PasswordOld = CryptogramUtil.SM2Decrypt(input.PasswordOld); input.PasswordNew = CryptogramUtil.SM2Decrypt(input.PasswordNew); var user = await _sysUserRep.GetByIdAsync(_userManager.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D0009); if (CryptogramUtil.CryptoType == CryptogramEnum.MD5.ToString()) { if (user.Password != MD5Encryption.Encrypt(input.PasswordOld)) throw Oops.Oh(ErrorCodeEnum.D1004); } else { if (CryptogramUtil.Decrypt(user.Password) != input.PasswordOld) throw Oops.Oh(ErrorCodeEnum.D1004); } if (input.PasswordOld == input.PasswordNew) throw Oops.Oh(ErrorCodeEnum.D1028); // 验证密码强度 if (CryptogramUtil.StrongPassword) { user.Password = input.PasswordNew.TryValidate(CryptogramUtil.PasswordStrengthValidation) ? CryptogramUtil.Encrypt(input.PasswordNew) : throw Oops.Oh(CryptogramUtil.PasswordStrengthValidationMsg); } else { user.Password = CryptogramUtil.Encrypt(input.PasswordNew); } var rows = await _sysUserRep.AsUpdateable(user).UpdateColumns(u => u.Password).ExecuteCommandAsync(); // 发布系统用户操作事件 if (rows > 0) await _eventPublisher.PublishAsync(SysUserEventTypeEnum.ChangePwd, new { Entity = user, Input = input }); return rows; } /// /// 重置用户密码 🔖 /// /// /// [DisplayName("重置用户密码")] public virtual async Task ResetPwd(ResetPwdUserInput input) { var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009); string randomPassword = new(Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 6).Select(s => s[Random.Shared.Next(s.Length)]).ToArray()); user.Password = CryptogramUtil.Encrypt(randomPassword); await _sysUserRep.AsUpdateable(user).UpdateColumns(u => u.Password).ExecuteCommandAsync(); // 清空密码错误次数 var keyErrorPasswordCount = $"{CacheConst.KeyPasswordErrorTimes}{user.Account}"; _sysCacheService.Remove(keyErrorPasswordCount); // 发布系统用户操作事件 await _eventPublisher.PublishAsync(SysUserEventTypeEnum.ResetPwd, new { Entity = user, Input = input }); return randomPassword; } /// /// 解除登录锁定 🔖 /// /// /// [DisplayName("解除登录锁定")] public virtual async Task UnlockLogin(UnlockLoginInput input) { var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009); // 清空密码错误次数 var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{user.Account}"; _sysCacheService.Remove(keyPasswordErrorTimes); // 发布系统用户操作事件 await _eventPublisher.PublishAsync(SysUserEventTypeEnum.UnlockLogin, new { Entity = user, Input = input }); } /// /// 获取用户拥有角色集合 🔖 /// /// /// [DisplayName("获取用户拥有角色集合")] public async Task> GetOwnRoleList(long userId) { return await _sysUserRoleService.GetUserRoleIdList(userId); } /// /// 获取用户扩展机构集合 🔖 /// /// /// [DisplayName("获取用户扩展机构集合")] public async Task> GetOwnExtOrgList(long userId) { return await _sysUserExtOrgService.GetUserExtOrgList(userId); } }