feat: initialize Evergreen Health backend

This commit is contained in:
fuenmao
2026-09-21 14:08:22 +08:00
commit 8553df5dd2
493 changed files with 75649 additions and 0 deletions
@@ -0,0 +1,35 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
public class UserExtOrgInput : BaseIdInput
{
/// <summary>
/// 机构Id
/// </summary>
public long OrgId { get; set; }
/// <summary>
/// 职位Id
/// </summary>
public long PosId { get; set; }
/// <summary>
/// 工号
/// </summary>
public string JobNum { get; set; }
/// <summary>
/// 职级
/// </summary>
public string PosLevel { get; set; }
/// <summary>
/// 入职日期
/// </summary>
public DateTime? JoinDate { get; set; }
}
@@ -0,0 +1,133 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 设置用户状态输入参数
/// </summary>
public class UserInput : BaseStatusInput
{
}
/// <summary>
/// 获取用户分页列表输入参数
/// </summary>
public class PageUserInput : BasePageInput
{
/// <summary>
/// 租户Id
/// </summary>
public long TenantId { get; set; }
/// <summary>
/// 账号
/// </summary>
public string Account { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string RealName { get; set; }
/// <summary>
/// 职位名称
/// </summary>
public string PosName { get; set; }
/// <summary>
/// 手机号
/// </summary>
public string Phone { get; set; }
/// <summary>
/// 查询时所选机构Id
/// </summary>
public long OrgId { get; set; }
}
/// <summary>
/// 增加用户输入参数
/// </summary>
public class AddUserInput : SysUser
{
/// <summary>
/// 账号
/// </summary>
[Required(ErrorMessage = "账号不能为空")]
public override string Account { get; set; }
/// <summary>
/// 真实姓名
/// </summary>
[Required(ErrorMessage = "真实姓名不能为空")]
public override string RealName { get; set; }
/// <summary>
/// 域用户
/// </summary>
public string DomainAccount { get; set; }
/// <summary>
/// 角色集合
/// </summary>
public List<long> RoleIdList { get; set; }
/// <summary>
/// 扩展机构集合
/// </summary>
public List<SysUserExtOrg> ExtOrgIdList { get; set; }
}
/// <summary>
/// 更新用户输入参数
/// </summary>
public class UpdateUserInput : AddUserInput
{
}
/// <summary>
/// 删除用户输入参数
/// </summary>
public class DeleteUserInput : BaseIdInput
{
/// <summary>
/// 机构Id
/// </summary>
public long OrgId { get; set; }
}
/// <summary>
/// 重置用户密码输入参数
/// </summary>
public class ResetPwdUserInput : BaseIdInput
{
}
/// <summary>
/// 修改用户密码输入参数
/// </summary>
public class ChangePwdInput
{
/// <summary>
/// 当前密码
/// </summary>
[Required(ErrorMessage = "当前密码不能为空")]
public string PasswordOld { get; set; }
/// <summary>
/// 新密码
/// </summary>
[Required(ErrorMessage = "新密码不能为空"), MinLength(5, ErrorMessage = "密码需要大于5个字符")]
public string PasswordNew { get; set; }
}
/// <summary>
/// 解除登录锁定输入参数
/// </summary>
public class UnlockLoginInput : BaseIdInput
{
}
@@ -0,0 +1,18 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统用户菜单快捷导航输入
/// </summary>
public class UserMenuInput
{
/// <summary>
/// 收藏菜单Id集合
/// </summary>
public List<long> MenuIdList { get; set; }
}
@@ -0,0 +1,30 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
public class UserOutput : SysUser
{
/// <summary>
/// 机构名称
/// </summary>
public string OrgName { get; set; }
/// <summary>
/// 职位名称
/// </summary>
public string PosName { get; set; }
/// <summary>
/// 角色名称
/// </summary>
public string RoleName { get; set; }
/// <summary>
/// 域用户
/// </summary>
public string DomainAccount { get; set; }
}
@@ -0,0 +1,72 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 注册方案分页查询输入参数
/// </summary>
public class PageUserRegWayInput : BasePageInput
{
/// <summary>
/// 方案名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 租户Id
/// </summary>
public long TenantId { get; set; }
}
/// <summary>
/// 注册方案增加输入参数
/// </summary>
public class AddUserRegWayInput : SysUserRegWay
{
/// <summary>
/// 方案名称
/// </summary>
[Required(ErrorMessage = "方案名称不能为空")]
[MaxLength(32, ErrorMessage = "方案名称字符长度不能超过32")]
public override string Name { get; set; }
/// <summary>
/// 账号类型
/// </summary>
[Enum(ErrorMessage = "账号类型不正确")]
public override AccountTypeEnum AccountType { get; set; }
/// <summary>
/// 角色
/// </summary>
[Required(ErrorMessage = "角色不能为空")]
public override long RoleId { get; set; }
/// <summary>
/// 机构
/// </summary>
[Required(ErrorMessage = "机构不能为空")]
public override long OrgId { get; set; }
/// <summary>
/// 职位
/// </summary>
[Required(ErrorMessage = "职位不能为空")]
public override long PosId { get; set; }
}
/// <summary>
/// 注册方案更新输入参数
/// </summary>
public class UpdateUserRegWayInput : AddUserRegWayInput
{
/// <summary>
/// 主键Id
/// </summary>
[Required(ErrorMessage = "主键Id不能为空")]
public override long Id { get; set; }
}
@@ -0,0 +1,28 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 注册方案输出参数
/// </summary>
public class UserRegWayOutput : SysUserRegWay
{
/// <summary>
/// 角色名称
/// </summary>
public string RoleName { get; set; }
/// <summary>
/// 机构名称
/// </summary>
public string OrgName { get; set; }
/// <summary>
/// 职位名称
/// </summary>
public string PosName { get; set; }
}
@@ -0,0 +1,23 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 授权用户角色
/// </summary>
public class UserRoleInput
{
/// <summary>
/// 用户Id
/// </summary>
public long UserId { get; set; }
/// <summary>
/// 角色Id集合
/// </summary>
public List<long> RoleIdList { get; set; }
}
@@ -0,0 +1,88 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统用户扩展机构服务
/// </summary>
public class SysUserExtOrgService : ITransient
{
private readonly SqlSugarRepository<SysUserExtOrg> _sysUserExtOrgRep;
public SysUserExtOrgService(SqlSugarRepository<SysUserExtOrg> sysUserExtOrgRep)
{
_sysUserExtOrgRep = sysUserExtOrgRep;
}
/// <summary>
/// 获取用户扩展机构集合
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task<List<SysUserExtOrg>> GetUserExtOrgList(long userId)
{
return await _sysUserExtOrgRep.GetListAsync(u => u.UserId == userId);
}
/// <summary>
/// 更新用户扩展机构
/// </summary>
/// <param name="userId"></param>
/// <param name="extOrgList"></param>
/// <returns></returns>
public async Task UpdateUserExtOrg(long userId, List<SysUserExtOrg> extOrgList)
{
await _sysUserExtOrgRep.DeleteAsync(u => u.UserId == userId);
if (extOrgList == null || extOrgList.Count < 1) return;
extOrgList.ForEach(u =>
{
u.UserId = userId;
});
await _sysUserExtOrgRep.InsertRangeAsync(extOrgList);
}
/// <summary>
/// 根据机构Id集合删除扩展机构
/// </summary>
/// <param name="orgIdList"></param>
/// <returns></returns>
public async Task DeleteUserExtOrgByOrgIdList(List<long> orgIdList)
{
await _sysUserExtOrgRep.DeleteAsync(u => orgIdList.Contains(u.OrgId));
}
/// <summary>
/// 根据用户Id删除扩展机构
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task DeleteUserExtOrgByUserId(long userId)
{
await _sysUserExtOrgRep.DeleteAsync(u => u.UserId == userId);
}
/// <summary>
/// 根据机构Id判断是否有用户
/// </summary>
/// <param name="orgId"></param>
/// <returns></returns>
public async Task<bool> HasUserOrg(long orgId)
{
return await _sysUserExtOrgRep.IsAnyAsync(u => u.OrgId == orgId);
}
/// <summary>
/// 根据职位Id判断是否有用户
/// </summary>
/// <param name="posId"></param>
/// <returns></returns>
public async Task<bool> HasUserPos(long posId)
{
return await _sysUserExtOrgRep.IsAnyAsync(u => u.PosId == posId);
}
}
@@ -0,0 +1,66 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 用户域账号服务
/// </summary>
public class SysUserLdapService : ITransient
{
private readonly SqlSugarRepository<SysUserLdap> _sysUserLdapRep;
public SysUserLdapService(SqlSugarRepository<SysUserLdap> sysUserLdapRep)
{
_sysUserLdapRep = sysUserLdapRep;
}
/// <summary>
/// 批量插入域账号
/// </summary>
/// <param name="tenantId"></param>
/// <param name="sysUserLdapList"></param>
/// <returns></returns>
public async Task InsertUserLdapList(long tenantId, List<SysUserLdap> sysUserLdapList)
{
await _sysUserLdapRep.DeleteAsync(u => u.TenantId == tenantId);
await _sysUserLdapRep.InsertRangeAsync(sysUserLdapList);
await _sysUserLdapRep.AsUpdateable()
.InnerJoin<SysUser>((l, u) => l.EmployeeId == u.Account)
.SetColumns((l, u) => new SysUserLdap { UserId = u.Id })
.Where((l, u) => l.TenantId == tenantId && u.Status == StatusEnum.Enable)
.ExecuteCommandAsync();
}
/// <summary>
/// 增加域账号
/// </summary>
/// <param name="tenantId"></param>
/// <param name="userId"></param>
/// <param name="account"></param>
/// <param name="domainAccount"></param>
/// <returns></returns>
public async Task AddUserLdap(long tenantId, long userId, string account, string domainAccount)
{
var userLdap = await _sysUserLdapRep.GetFirstAsync(u => u.TenantId == tenantId && (u.Account == account || u.UserId == userId || u.EmployeeId == domainAccount));
if (userLdap != null) await _sysUserLdapRep.DeleteByIdAsync(userLdap.Id);
if (!string.IsNullOrWhiteSpace(domainAccount))
await _sysUserLdapRep.InsertAsync(new SysUserLdap { EmployeeId = account, TenantId = tenantId, UserId = userId, Account = domainAccount });
}
/// <summary>
/// 删除域账号
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task DeleteUserLdapByUserId(long userId)
{
await _sysUserLdapRep.DeleteAsync(u => u.UserId == userId);
}
}
@@ -0,0 +1,101 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统用户菜单快捷导航服务 🧩
/// </summary>
[ApiDescriptionSettings(Order = 445)]
public class SysUserMenuService : IDynamicApiController, ITransient
{
private readonly SqlSugarRepository<SysUserMenu> _sysUserMenuRep;
private readonly UserManager _userManager;
public SysUserMenuService(SqlSugarRepository<SysUserMenu> sysUserMenuRep, UserManager userManager)
{
_sysUserMenuRep = sysUserMenuRep;
_userManager = userManager;
}
/// <summary>
/// 收藏菜单 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[UnitOfWork]
[DisplayName("收藏菜单")]
[ApiDescriptionSettings(Name = "Add"), HttpPost]
public async Task AddUserMenu(UserMenuInput input)
{
await _sysUserMenuRep.DeleteAsync(u => u.UserId == _userManager.UserId);
if (input.MenuIdList == null || input.MenuIdList.Count == 0) return;
var menus = input.MenuIdList.Select(u => new SysUserMenu
{
UserId = _userManager.UserId,
MenuId = u
}).ToList();
await _sysUserMenuRep.InsertRangeAsync(menus);
}
/// <summary>
/// 取消收藏菜单 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[ApiDescriptionSettings(Name = "DeleteUserMenu"), HttpPost]
[DisplayName("取消收藏菜单")]
public async Task DeleteUserMenu(UserMenuInput input)
{
await _sysUserMenuRep.DeleteAsync(u => u.UserId == _userManager.UserId && input.MenuIdList.Contains(u.MenuId));
}
/// <summary>
/// 获取当前用户收藏的菜单集合 🔖
/// </summary>
/// <returns></returns>
[DisplayName("获取当前用户收藏的菜单集合")]
public async Task<List<MenuOutput>> GetUserMenuList()
{
var sysUserMenuList = await _sysUserMenuRep.AsQueryable()
.Includes(u => u.SysMenu)
.Where(u => u.UserId == _userManager.UserId).ToListAsync();
return sysUserMenuList.Where(u => u.SysMenu != null).Select(u => u.SysMenu).ToList().Adapt<List<MenuOutput>>();
}
/// <summary>
/// 获取当前用户收藏的菜单Id集合 🔖
/// </summary>
/// <returns></returns>
[DisplayName("获取当前用户收藏的菜单Id集合")]
public async Task<List<long>> GetUserMenuIdList()
{
return await _sysUserMenuRep.AsQueryable()
.Where(u => u.UserId == _userManager.UserId).Select(u => u.MenuId).ToListAsync();
}
/// <summary>
/// 删除指定用户的收藏菜单
/// </summary>
/// <returns></returns>
[NonAction]
public async Task DeleteUserMenuList(long userId)
{
await _sysUserMenuRep.DeleteAsync(u => u.UserId == userId);
}
/// <summary>
/// 批量删除收藏菜单
/// </summary>
/// <param name="ids"></param>
[NonAction]
public async Task DeleteMenuList(List<long> ids)
{
if (ids == null || ids.Count == 0) return;
await _sysUserMenuRep.DeleteAsync(u => ids.Contains(u.MenuId));
}
}
@@ -0,0 +1,118 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统用户注册方案服务 🧩
/// </summary>
[ApiDescriptionSettings(Order = 490)]
public class SysUserRegWayService : IDynamicApiController, ITransient
{
private readonly SqlSugarRepository<SysUserRegWay> _sysUserRegWayRep;
private readonly UserManager _userManager;
public SysUserRegWayService(SqlSugarRepository<SysUserRegWay> sysUserRegWayRep, UserManager userManager)
{
_sysUserRegWayRep = sysUserRegWayRep;
_userManager = userManager;
}
/// <summary>
/// 查询注册方案列表 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("查询注册方案列表")]
[ApiDescriptionSettings(Name = "List"), HttpPost]
public async Task<List<UserRegWayOutput>> List(PageUserRegWayInput input)
{
input.Keyword = input.Keyword?.Trim();
var query = _sysUserRegWayRep.AsQueryable()
.WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
.WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Name.Contains(input.Keyword))
.WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
.LeftJoin<SysRole>((u, a) => u.RoleId == a.Id)
.LeftJoin<SysOrg>((u, a, b) => u.OrgId == b.Id)
.LeftJoin<SysPos>((u, a, b, c) => u.PosId == c.Id)
.Select((u, a, b, c) => new UserRegWayOutput
{
RoleName = a.Name,
OrgName = b.Name,
PosName = c.Name,
}, true);
return await query.OrderBuilder(input).ToListAsync();
}
/// <summary>
/// 增加注册方案 ➕
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("增加注册方案")]
[ApiDescriptionSettings(Name = "Add"), HttpPost]
public async Task<long> Add(AddUserRegWayInput input)
{
var entity = input.Adapt<SysUserRegWay>();
if (await _sysUserRegWayRep.IsAnyAsync(u => u.Name == input.Name)) throw Oops.Oh(ErrorCodeEnum.D2101);
await CheckData(input);
return await _sysUserRegWayRep.InsertAsync(entity) ? entity.Id : 0;
}
/// <summary>
/// 更新注册方案 ✏️
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("更新注册方案")]
[ApiDescriptionSettings(Name = "Update"), HttpPost]
public async Task Update(UpdateUserRegWayInput input)
{
if (await _sysUserRegWayRep.IsAnyAsync(u => u.Id != input.Id && u.Name == input.Name)) throw Oops.Oh(ErrorCodeEnum.D2101);
await CheckData(input);
await _sysUserRegWayRep.AsUpdateable(input).ExecuteCommandAsync();
}
/// <summary>
/// 检查数据
/// </summary>
/// <param name="input"></param>
[NonAction]
public async Task CheckData(AddUserRegWayInput input)
{
// 检查外键数据是否存在
if (!await _sysUserRegWayRep.Context.Queryable<SysRole>().AnyAsync(u => u.Id == input.RoleId)) throw Oops.Oh(ErrorCodeEnum.D1036);
if (!await _sysUserRegWayRep.Context.Queryable<SysOrg>().AnyAsync(u => u.Id == input.OrgId)) throw Oops.Oh(ErrorCodeEnum.D2011);
if (!await _sysUserRegWayRep.Context.Queryable<SysPos>().AnyAsync(u => u.Id == input.PosId)) throw Oops.Oh(ErrorCodeEnum.D6003);
// 禁止注册超级管理员和系统管理员
if (input.AccountType is AccountTypeEnum.SysAdmin or AccountTypeEnum.SuperAdmin) throw Oops.Oh(ErrorCodeEnum.D1037);
}
/// <summary>
/// 删除注册方案 ❌
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[UnitOfWork]
[DisplayName("删除注册方案")]
[ApiDescriptionSettings(Name = "Delete"), HttpPost]
public async Task Delete(BaseIdInput input)
{
var entity = await _sysUserRegWayRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
// 关闭相关租户注册功能
await _sysUserRegWayRep.Context.Updateable(new SysTenant { EnableReg = YesNoEnum.N, RegWayId = null })
.UpdateColumns(u => new { u.EnableReg, u.RegWayId })
.Where(u => u.RegWayId == input.Id)
.ExecuteCommandAsync();
// 删除方案
await _sysUserRegWayRep.DeleteAsync(entity);
}
}
@@ -0,0 +1,106 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统用户角色服务
/// </summary>
public class SysUserRoleService : ITransient
{
private readonly SysCacheService _sysCacheService;
private readonly SqlSugarRepository<SysUserRole> _sysUserRoleRep;
public SysUserRoleService(SysCacheService sysCacheService,
SqlSugarRepository<SysUserRole> sysUserRoleRep)
{
_sysCacheService = sysCacheService;
_sysUserRoleRep = sysUserRoleRep;
}
/// <summary>
/// 授权用户角色
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task GrantUserRole(UserRoleInput input)
{
await _sysUserRoleRep.DeleteAsync(u => u.UserId == input.UserId);
if (input.RoleIdList == null || input.RoleIdList.Count < 1) return;
var roles = input.RoleIdList.Select(u => new SysUserRole
{
UserId = input.UserId,
RoleId = u
}).ToList();
await _sysUserRoleRep.InsertRangeAsync(roles);
_sysCacheService.Remove(CacheConst.KeyUserButton + input.UserId);
}
/// <summary>
/// 根据角色Id删除用户角色
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public async Task DeleteUserRoleByRoleId(long roleId)
{
await _sysUserRoleRep.AsQueryable()
.Where(u => u.RoleId == roleId)
.Select(u => u.UserId)
.ForEachAsync(userId =>
{
_sysCacheService.Remove(CacheConst.KeyUserButton + userId);
});
await _sysUserRoleRep.DeleteAsync(u => u.RoleId == roleId);
}
/// <summary>
/// 根据用户Id删除用户角色
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task DeleteUserRoleByUserId(long userId)
{
await _sysUserRoleRep.DeleteAsync(u => u.UserId == userId);
_sysCacheService.Remove(CacheConst.KeyUserButton + userId);
}
/// <summary>
/// 根据用户Id获取角色集合
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task<List<SysRole>> GetUserRoleList(long userId)
{
var sysUserRoleList = await _sysUserRoleRep.AsQueryable()
.Includes(u => u.SysRole)
.Where(u => u.UserId == userId).ToListAsync();
return sysUserRoleList.Where(u => u.SysRole != null).Select(u => u.SysRole).ToList();
}
/// <summary>
/// 根据用户Id获取角色Id集合
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task<List<long>> GetUserRoleIdList(long userId)
{
return await _sysUserRoleRep.AsQueryable()
.Where(u => u.UserId == userId).Select(u => u.RoleId).ToListAsync();
}
/// <summary>
/// 根据角色Id获取用户Id集合
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public async Task<List<long>> GetUserIdList(long roleId)
{
return await _sysUserRoleRep.AsQueryable()
.Where(u => u.RoleId == roleId).Select(u => u.UserId).ToListAsync();
}
}
@@ -0,0 +1,505 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统用户服务 🧩
/// </summary>
[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<SysUser> _sysUserRep;
private readonly IEventPublisher _eventPublisher;
public SysUserService(UserManager userManager,
SysOrgService sysOrgService,
SysUserExtOrgService sysUserExtOrgService,
SysUserRoleService sysUserRoleService,
SysConfigService sysConfigService,
SysOnlineUserService sysOnlineUserService,
SysCacheService sysCacheService,
SysUserLdapService sysUserLdapService,
SqlSugarRepository<SysUser> 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;
}
/// <summary>
/// 获取用户分页列表 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("获取用户分页列表")]
public virtual async Task<SqlSugarPagedList<UserOutput>> Page(PageUserInput input)
{
//获取子节点Id集合(包含自己)
var orgList = await _sysOrgService.GetChildIdListWithSelfById(input.OrgId);
return await _sysUserRep.AsQueryable()
.LeftJoin<SysOrg>((u, a) => u.OrgId == a.Id)
.LeftJoin<SysPos>((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<SysUserRole>().LeftJoin<SysRole>((m, n) => m.RoleId == n.Id).Where(m => m.UserId == u.Id).SelectStringJoin((m, n) => n.Name, ","),
DomainAccount = SqlFunc.Subqueryable<SysUserLdap>().Where(m => m.UserId == u.Id).Select(m => m.Account)
}, true)
.ToPagedListAsync(input.Page, input.PageSize);
}
/// <summary>
/// 增加用户 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[UnitOfWork]
[ApiDescriptionSettings(Name = "Add"), HttpPost]
[DisplayName("增加用户")]
public virtual async Task<long> 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 = !string.IsNullOrWhiteSpace(input.Password) ? input.Password : await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
var user = input.Adapt<SysUser>();
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;
}
/// <summary>
/// 注册用户 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[NonAction]
public virtual async Task<long> 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<string>(ConfigConst.SysPassword);
input.Password = CryptogramUtil.Encrypt(password);
}
var user = input.Adapt<SysUser>();
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;
}
/// <summary>
/// 更新用户 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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<SysUser>()).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
});
}
/// <summary>
/// 更新当前用户语言 🔖
/// </summary>
/// <param name="langCode"></param>
/// <returns></returns>
[UnitOfWork]
[ApiDescriptionSettings(Name = "SetLangCode"), HttpPost]
[DisplayName("更新当前用户语言")]
public virtual async Task SetLangCode(string langCode)
{
var user = await _sysUserRep.AsQueryable().ClearFilter().FirstAsync(u => u.Id == _userManager.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D1011).StatusCode(401);
user.LangCode = langCode;
await _sysUserRep.AsUpdateable(user).UpdateColumns(it => it.LangCode).ExecuteCommandAsync();
}
/// <summary>
/// 更新角色和扩展机构
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private async Task UpdateRoleAndExtOrg(AddUserInput input)
{
await GrantRole(new UserRoleInput { UserId = input.Id, RoleIdList = input.RoleIdList });
await _sysUserExtOrgService.UpdateUserExtOrg(input.Id, input.ExtOrgIdList);
}
/// <summary>
/// 删除用户 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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<SqlSugarRepository<SysTenant>>().IsAnyAsync(u => u.UserId == input.Id);
if (isTenantUser) throw Oops.Oh(ErrorCodeEnum.D1029);
// 若账号为开放接口绑定账号则禁止删除
var isOpenAccessUser = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysOpenAccess>>().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
});
}
/// <summary>
/// 查看用户基本信息 🔖
/// </summary>
/// <returns></returns>
[DisplayName("查看用户基本信息")]
public virtual async Task<SysUser> GetBaseInfo()
{
return await _sysUserRep.AsQueryable().ClearFilter().FirstAsync(c => c.Id == _userManager.UserId);
}
/// <summary>
/// 查询用户组织机构信息 🔖
/// </summary>
/// <returns></returns>
[DisplayName("查询用户组织机构信息")]
public virtual async Task<List<OrgTreeOutput>> GetOrgInfo()
{
return await _sysOrgService.GetTree(new OrgInput { Id = 0 });
}
/// <summary>
/// 更新用户基本信息 🔖
/// </summary>
/// <returns></returns>
[ApiDescriptionSettings(Name = "BaseInfo"), HttpPost]
[DisplayName("更新用户基本信息")]
public virtual async Task<int> UpdateBaseInfo(SysUser user)
{
return await _sysUserRep.AsUpdateable(user)
.IgnoreColumns(u => new { u.CreateTime, u.Account, u.Password, u.AccountType, u.OrgId, u.PosId }).ExecuteCommandAsync();
}
/// <summary>
/// 设置用户状态 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[UnitOfWork]
[DisplayName("设置用户状态")]
public virtual async Task<int> 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<SysCacheService>();
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;
}
/// <summary>
/// 授权用户角色 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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);
}
/// <summary>
/// 修改用户密码 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("修改用户密码")]
public virtual async Task<int> ChangePwd(ChangePwdInput input)
{
// 国密SM2解密(前端密码传输SM2加密后的)
input.PasswordOld = CryptogramUtil.SM2Decrypt(input.PasswordOld);
input.PasswordNew = CryptogramUtil.SM2Decrypt(input.PasswordNew);
var user = await _sysUserRep.AsQueryable().ClearFilter().FirstAsync(c => c.Id == _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;
}
/// <summary>
/// 重置用户密码 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("重置用户密码")]
public virtual async Task<string> 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;
}
/// <summary>
/// 解除登录锁定 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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
});
}
/// <summary>
/// 获取用户拥有角色集合 🔖
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
[DisplayName("获取用户拥有角色集合")]
public async Task<List<long>> GetOwnRoleList(long userId)
{
return await _sysUserRoleService.GetUserRoleIdList(userId);
}
/// <summary>
/// 获取用户扩展机构集合 🔖
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
[DisplayName("获取用户扩展机构集合")]
public async Task<List<SysUserExtOrg>> GetOwnExtOrgList(long userId)
{
return await _sysUserExtOrgService.GetUserExtOrgList(userId);
}
}
@@ -0,0 +1,67 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 当前登录用户
/// </summary>
public class UserManager : IScoped
{
private readonly IHttpContextAccessor _httpContextAccessor;
/// <summary>
/// 用户ID
/// </summary>
public long UserId => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.UserId)?.Value).ToLong();
/// <summary>
/// 租户ID
/// </summary>
public long TenantId => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.TenantId)?.Value).ToLong();
/// <summary>
/// 用户账号
/// </summary>
public string Account => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.Account)?.Value;
/// <summary>
/// 真实姓名
/// </summary>
public string RealName => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.RealName)?.Value;
/// <summary>
/// 账号类型
/// </summary>
public AccountTypeEnum? AccountType => int.TryParse(_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value, out var val) ? (AccountTypeEnum?)val : null;
/// <summary>
/// 是否超级管理员
/// </summary>
public bool SuperAdmin => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SuperAdmin).ToString();
/// <summary>
/// 是否系统管理员
/// </summary>
public bool SysAdmin => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SysAdmin).ToString();
/// <summary>
/// 组织机构Id
/// </summary>
public long OrgId => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OrgId)?.Value).ToLong();
/// <summary>
/// 微信OpenId
/// </summary>
public string OpenId => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OpenId)?.Value;
public string LangCode => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.LangCode)?.Value ?? "zh_CN";
public UserManager(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
}