using iWare.Wms.Core; using Furion.DatabaseAccessor; using Furion.DatabaseAccessor.Extensions; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; using Mapster; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace iWare.Wms.Application { /// /// 角色服务 /// [ApiDescriptionSettings(Name = "Role", Order = 149)] [Route("api")] public class SysRoleService : ISysRoleService, IDynamicApiController, ITransient { private readonly IRepository _sysRoleRep; // 角色表仓储 private readonly IRepository _sysUserRoleRep; // 用户角色表仓储 private readonly ISysRoleDataScopeService _sysRoleDataScopeService; private readonly ISysOrgService _sysOrgService; private readonly ISysRoleMenuService _sysRoleMenuService; private readonly ISysCacheService _sysCacheService; public SysRoleService(IRepository sysRoleRep, IRepository sysUserRoleRep, ISysRoleDataScopeService sysRoleDataScopeService, ISysOrgService sysOrgService, ISysRoleMenuService sysRoleMenuService, ISysCacheService sysCacheService) { _sysRoleRep = sysRoleRep; _sysUserRoleRep = sysUserRoleRep; _sysRoleDataScopeService = sysRoleDataScopeService; _sysOrgService = sysOrgService; _sysRoleMenuService = sysRoleMenuService; _sysCacheService = sysCacheService; } /// /// 获取用户角色相关信息(登录) /// /// /// [NonAction] public async Task> GetUserRoleList(long userId) { return await _sysUserRoleRep.Include(m => m.SysRole, false) .Where(m => m.SysUserId == userId && m.SysRole.Status == CommonStatus.ENABLE) .Select(m => new RoleOutput { Id = m.SysRoleId, Code = m.SysRole.Code, Name = m.SysRole.Name }).ToListAsync(); } /// /// 分页获取角色列表 /// /// /// [HttpGet("sysRole/page")] public async Task> QueryRolePageList([FromQuery] RolePageInput input) { var name = !string.IsNullOrEmpty(input.Name?.Trim()); var code = !string.IsNullOrEmpty(input.Code?.Trim()); var roles = await _sysRoleRep.DetachedEntities .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")), (code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%"))) .Where(u => u.Status == CommonStatus.ENABLE).OrderBy(u => u.Sort) .ToADPagedListAsync(input.PageNo, input.PageSize); return roles; } /// /// 获取角色列表 /// /// /// [NonAction] public async Task GetRoleList([FromQuery] RoleInput input) { var name = !string.IsNullOrEmpty(input.Name?.Trim()); var code = !string.IsNullOrEmpty(input.Code?.Trim()); return await _sysRoleRep.DetachedEntities .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")), (code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%"))) .Where(u => u.Status == CommonStatus.ENABLE) .OrderBy(u => u.Sort) .Select(u => new { u.Id, Name = u.Name + "[" + u.Code + "]", }) .ToListAsync(); } /// /// 角色下拉(用于授权角色时选择) /// /// [HttpGet("sysRole/dropDown")] public async Task> GetRoleDropDown() { // 如果不是超级管理员,则查询自己拥有的角色集合 var roles = CurrentUserInfo.IsSuperAdmin ? await _sysUserRoleRep.Where(u => u.SysUserId == CurrentUserInfo.UserId).Select(u => u.SysRoleId).ToListAsync() : new List(); return await _sysRoleRep.DetachedEntities .Where(roles.Count > 0, u => roles.Contains(u.Id)) .Where(u => u.Status == CommonStatus.ENABLE) .ProjectToType() .ToListAsync(); } /// /// 增加角色 /// /// /// [HttpPost("sysRole/add")] public async Task AddRole(AddRoleInput input) { var isExist = await _sysRoleRep.DetachedEntities.AnyAsync(u => u.Code == input.Code || u.Name == input.Name); if (isExist) throw Oops.Oh(ErrorCode.D1006); var role = input.Adapt(); role.DataScopeType = DataScopeType.ALL; // 新角色默认全部数据范围 await role.InsertAsync(); } /// /// 删除角色 /// /// /// [HttpPost("sysRole/delete")] [UnitOfWork] public async Task DeleteRole(DeleteRoleInput input) { var sysRole = await _sysRoleRep.FirstOrDefaultAsync(u => u.Id == input.Id); //if (sysRole.Code == CommonConst.SYS_MANAGER_ROLE_CODE) // throw Oops.Oh(ErrorCode.D1019); await sysRole.DeleteAsync(); //级联删除该角色对应的角色-数据范围关联信息 await _sysRoleDataScopeService.DeleteRoleDataScopeListByRoleId(sysRole.Id); ////级联删除该角色对应的用户-角色表关联信息 //await _sysUserRoleService.DeleteUserRoleListByRoleId(sysRole.Id); // 避免循环引用,故用下面逻辑 var userRoles = await _sysUserRoleRep.Where(u => u.SysRoleId == sysRole.Id).ToListAsync(); await _sysUserRoleRep.DeleteAsync(userRoles); //级联删除该角色对应的角色-菜单表关联信息 await _sysRoleMenuService.DeleteRoleMenuListByRoleId(sysRole.Id); } /// /// 更新角色 /// /// /// [HttpPost("sysRole/edit")] public async Task UpdateRole(UpdateRoleInput input) { var adminRole = await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id); //if (adminRole.Code == CommonConst.SYS_MANAGER_ROLE_CODE) // throw Oops.Oh(ErrorCode.D1020); var isExist = await _sysRoleRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id); if (isExist) throw Oops.Oh(ErrorCode.D1006); var sysRole = input.Adapt(); await sysRole.UpdateExcludeAsync(new[] { nameof(SysRole.DataScopeType) }, true); } /// /// 获取角色 /// /// /// [HttpGet("sysRole/detail")] public async Task GetRoleInfo([FromQuery] QueryRoleInput input) { return await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id); } /// /// 授权角色菜单 /// /// /// [HttpPost("sysRole/grantMenu")] public async Task GrantMenu(GrantRoleMenuInput input) { var adminRole = await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id); //if (!CurrentUserInfo.IsSuperAdmin && adminRole.Code == CommonConst.SYS_MANAGER_ROLE_CODE) // throw Oops.Oh(ErrorCode.D1021); await _sysRoleMenuService.GrantMenu(input); } /// /// 授权角色数据范围 /// /// /// [HttpPost("sysRole/grantData")] public async Task GrantData(GrantRoleDataInput input) { // 清除所有用户数据范围缓存 await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_DATASCOPE); var role = await _sysRoleRep.FirstOrDefaultAsync(u => u.Id == input.Id); var dataScopeType = input.DataScopeType; if (!CurrentUserInfo.IsSuperAdmin) { //如果授权的角色的数据范围类型为全部,则没权限,只有超级管理员有 if ((int)DataScopeType.ALL == dataScopeType) throw Oops.Oh(ErrorCode.D1016); //如果授权的角色数据范围类型为自定义,则要判断授权的数据范围是否在自己的数据范围内 if ((int)DataScopeType.DEFINE == dataScopeType) { var dataScopes = await _sysOrgService.GetUserDataScopeIdList(); var grantOrgIdList = input.GrantOrgIdList; //要授权的数据范围列表 if (grantOrgIdList.Count > 0) { if (dataScopes.Count < 1) throw Oops.Oh(ErrorCode.D1016); //else if (!dataScopes.All(u => grantOrgIdList.Any(c => c == u))) // throw Oops.Oh(ErrorCode.D1016); else if (!grantOrgIdList.All(u => dataScopes.Any(c => c == u))) throw Oops.Oh(ErrorCode.D1016); } } } role.DataScopeType = (DataScopeType)dataScopeType; await _sysRoleDataScopeService.GrantDataScope(input); } /// /// 根据角色Id集合获取数据范围Id集合 /// /// /// /// [NonAction] public async Task> GetUserDataScopeIdList(List roleIdList, long orgId) { // 定义角色中最大数据范围的类型,目前按最大范围策略来,如果你同时拥有ALL和SELF的权限,最后按ALL返回 int strongerDataScopeType = (int)DataScopeType.SELF; var customDataScopeRoleIdList = new List(); if (roleIdList != null && roleIdList.Count > 0) { var roles = await _sysRoleRep.DetachedEntities.Where(u => roleIdList.Contains(u.Id)).ToListAsync(); roles.ForEach(u => { if (u.DataScopeType == DataScopeType.DEFINE) customDataScopeRoleIdList.Add(u.Id); else if ((int)u.DataScopeType <= strongerDataScopeType) strongerDataScopeType = (int)u.DataScopeType; }); } // 自定义数据范围的角色对应的数据范围 var roleDataScopeIdList = await _sysRoleDataScopeService.GetRoleDataScopeIdList(customDataScopeRoleIdList); // 角色中拥有最大数据范围类型的数据范围 var dataScopeIdList = await _sysOrgService.GetDataScopeListByDataScopeType(strongerDataScopeType, orgId); return roleDataScopeIdList.Concat(dataScopeIdList).Distinct().ToList(); //并集 } /// /// 根据角色Id获取角色名称 /// /// /// [NonAction] public async Task GetNameByRoleId(long roleId) { var role = await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == roleId); if (role == null) throw Oops.Oh(ErrorCode.D1002); return role.Name; } /// /// 获取角色拥有菜单Id集合 /// /// /// [HttpGet("sysRole/ownMenu")] public async Task> OwnMenu([FromQuery] QueryRoleInput input) { return await _sysRoleMenuService.GetRoleMenuIdList(new List { input.Id }); } /// /// 获取角色拥有数据Id集合 /// /// /// [HttpGet("sysRole/ownData")] public async Task> OwnData([FromQuery] QueryRoleInput input) { return await _sysRoleDataScopeService.GetRoleDataScopeIdList(new List { input.Id }); } } }