Files
ThingsGateway/src/Admin/ThingsGateway.Admin.Application/Services/Role/SysRoleService.cs

521 lines
21 KiB
C#
Raw Normal View History

2025-01-24 22:42:26 +08:00
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
using ThingsGateway.FriendlyException;
using ThingsGateway.NewLife.Json.Extension;
namespace ThingsGateway.Admin.Application;
internal sealed class SysRoleService : BaseService<SysRole>, ISysRoleService
{
private readonly IRelationService _relationService;
private readonly ISysResourceService _sysResourceService;
private readonly ISysOrgService _sysOrgService;
private ISysUserService _sysUserService;
private ISysUserService SysUserService
{
get
{
if (_sysUserService == null)
{
_sysUserService = App.GetService<ISysUserService>();
}
return _sysUserService;
}
}
private IDispatchService<SysRole> _dispatchService;
public SysRoleService(IRelationService relationService, ISysResourceService sysResourceService, ISysOrgService sysOrgService, IDispatchService<SysRole> dispatchService)
{
_relationService = relationService;
_sysResourceService = sysResourceService;
_sysOrgService = sysOrgService;
_dispatchService = dispatchService;
}
#region
/// <inheritdoc/>
public async Task<List<RoleTreeOutput>> TreeAsync()
{
var result = new List<RoleTreeOutput>();//返回结果
var sysOrgList = await _sysOrgService.GetAllAsync(false).ConfigureAwait(false);//获取所有机构
var sysRoles = await GetAllAsync().ConfigureAwait(false);//获取所有角色
var dataScope = await SysUserService.GetCurrentUserDataScopeAsync().ConfigureAwait(false);
sysOrgList = sysOrgList
.WhereIF(dataScope != null && dataScope?.Count > 0, b => dataScope.Contains(b.Id))
.WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId)
.ToList();//在指定组织列表查询
sysRoles = sysRoles
.WhereIF(dataScope != null && dataScope?.Count > 0, b => dataScope.Contains(b.OrgId))
.WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId)
.ToList();//在指定职位列表查询
var topOrgList = sysOrgList.Where(it => it.ParentId == 0);//获取顶级机构
var globalRole = sysRoles.Where(it => it.Category == RoleCategoryEnum.Global);//获取全局角色
2025-07-24 19:46:30 +08:00
var children = globalRole.Select(it => new RoleTreeOutput
2025-01-24 22:42:26 +08:00
{
2025-07-24 19:46:30 +08:00
Id = it.Id,
Name = it.Name,
IsRole = true
}).ToList();
result.Add(new RoleTreeOutput()
{
Id = CommonUtils.GetSingleId(),
Name = Localizer["Global"],
Children = children
});//添加全局角色
2025-01-24 22:42:26 +08:00
//遍历顶级机构
foreach (var org in topOrgList)
{
var childIds = await _sysOrgService.GetOrgChildIdsAsync(org.Id, true, sysOrgList).ConfigureAwait(false);//获取机构下的所有子级ID
var childRoles = sysRoles.Where(it => it.OrgId != 0 && childIds.Contains(it.OrgId));//获取机构下的所有角色
2025-07-24 19:46:30 +08:00
List<RoleTreeOutput> childrenRoleTreeOutputs = new();
foreach (var it in childRoles)
{
childrenRoleTreeOutputs.Add(new RoleTreeOutput()
{
Id = it.Id,
Name = it.Name,
IsRole = true
});
}
if (childrenRoleTreeOutputs.Count > 0)
2025-01-24 22:42:26 +08:00
{
var roleTreeOutput = new RoleTreeOutput
{
Id = org.Id,
Name = org.Name,
2025-07-24 19:46:30 +08:00
IsRole = false,
Children = childrenRoleTreeOutputs
2025-01-24 22:42:26 +08:00
};//实例化角色树
result.Add(roleTreeOutput);
}
}
return result;
}
/// <summary>
/// 从缓存/数据库获取全部角色信息
/// </summary>
/// <returns>角色列表</returns>
public async Task<List<SysRole>> GetAllAsync()
{
var key = CacheConst.Cache_SysRole;
var sysRoles = App.CacheService.Get<List<SysRole>>(key);
if (sysRoles == null)
{
using var db = GetDB();
sysRoles = await db.Queryable<SysRole>().ToListAsync().ConfigureAwait(false);
App.CacheService.Set(key, sysRoles);
}
return sysRoles;
}
/// <summary>
/// 根据用户id获取角色列表
/// </summary>
/// <param name="userId">用户id</param>
/// <returns>角色列表</returns>
public async Task<IEnumerable<SysRole>> GetRoleListByUserIdAsync(long userId)
{
var roleList = await _relationService.GetRelationListByObjectIdAndCategoryAsync(userId, RelationCategoryEnum.UserHasRole).ConfigureAwait(false);//根据用户ID获取角色ID
var roleIdList = roleList.Select(x => x.TargetId.ToLong());//角色ID列表
return (await GetAllAsync().ConfigureAwait(false)).Where(it => roleIdList.Contains(it.Id));
}
/// <inheritdoc/>
public async Task<QueryData<SysRole>> PageAsync(QueryPageOptions option, Func<ISugarQueryable<SysRole>, ISugarQueryable<SysRole>>? queryFunc = null)
{
var dataScope = await SysUserService.GetCurrentUserDataScopeAsync().ConfigureAwait(false); //获取机构ID范围
queryFunc += a => a
.WhereIF(dataScope != null && dataScope?.Count > 0, b => dataScope.Contains(b.OrgId))
.WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId);
return await QueryAsync(option, queryFunc).ConfigureAwait(false);
}
/// <summary>
/// 根据角色id获取角色列表
/// </summary>
/// <param name="input">角色id列表</param>
/// <returns>角色列表</returns>
2025-07-24 19:46:30 +08:00
public async Task<IEnumerable<SysRole>> GetRoleListByIdListAsync(HashSet<long> input)
2025-01-24 22:42:26 +08:00
{
var roles = await GetAllAsync().ConfigureAwait(false);
var roleList = roles.Where(it => input.Contains(it.Id));
return roleList;
}
#endregion
#region
/// <summary>
/// 删除角色
/// </summary>
/// <param name="ids">id列表</param>
[OperDesc("DeleteRole")]
2025-07-24 19:46:30 +08:00
public async Task<bool> DeleteRoleAsync(HashSet<long> ids)
2025-01-24 22:42:26 +08:00
{
var sysRoles = await GetAllAsync().ConfigureAwait(false);//获取所有角色
var hasSuperAdmin = sysRoles.Any(it => it.Id == RoleConst.SuperAdminRoleId && ids.Contains(it.Id));//判断是否有超级管理员
if (hasSuperAdmin)
throw Oops.Bah(Localizer["CanotDeleteAdmin"]);
var dels = (await GetAllAsync().ConfigureAwait(false)).Where(a => ids.Contains(a.Id));
2025-07-24 19:46:30 +08:00
await SysUserService.CheckApiDataScopeAsync(dels.Select(a => a.OrgId), dels.Select(a => a.CreateUserId)).ConfigureAwait(false);
2025-01-24 22:42:26 +08:00
//数据库是string所以这里转下
2025-07-24 19:46:30 +08:00
var targetIds = ids.Select(it => it.ToString()).ToList();
2025-01-24 22:42:26 +08:00
//定义删除的关系
var delRelations = new List<RelationCategoryEnum> {
RelationCategoryEnum.RoleHasResource,
RelationCategoryEnum.RoleHasPermission,
RelationCategoryEnum.RoleHasModule,
RelationCategoryEnum.RoleHasOpenApiPermission };
using var db = GetDB();
//事务
var result = await db.UseTranAsync(async () =>
{
2025-07-24 19:46:30 +08:00
await db.Deleteable<SysRole>().In(ids).ExecuteCommandHasChangeAsync().ConfigureAwait(false);//删除
2025-01-24 22:42:26 +08:00
//删除关系表角色与资源关系,角色与权限关系
await db.Deleteable<SysRelation>(it => ids.Contains(it.ObjectId) && delRelations.Contains(it.Category)).ExecuteCommandAsync().ConfigureAwait(false);
//删除关系表角色与用户关系
await db.Deleteable<SysRelation>(it => targetIds.Contains(it.TargetId) && it.Category == RelationCategoryEnum.UserHasRole).ExecuteCommandAsync().ConfigureAwait(false);
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
RefreshCache();//刷新缓存
_relationService.RefreshCache(RelationCategoryEnum.UserHasRole);//关系表刷新UserHasRole缓存
_relationService.RefreshCache(RelationCategoryEnum.RoleHasResource);//关系表刷新RoleHasResource缓存
_relationService.RefreshCache(RelationCategoryEnum.RoleHasPermission);//关系表刷新RoleHasPermission缓存
_relationService.RefreshCache(RelationCategoryEnum.RoleHasModule);//关系表刷新RoleHasModule缓存
_relationService.RefreshCache(RelationCategoryEnum.RoleHasOpenApiPermission);//关系表刷新RoleHasOpenApiPermission缓存
await ClearTokenUtil.DeleteUserCacheByRoleIds(ids).ConfigureAwait(false);//清除角色下用户缓存
return true;
}
else
{
throw new(result.ErrorMessage, result.ErrorException);
}
}
/// <summary>
/// 保存角色
/// </summary>
/// <param name="input">角色</param>
/// <param name="type">保存类型</param>
[OperDesc("SaveRole")]
public async Task<bool> SaveRoleAsync(SysRole input, ItemChangedType type)
{
await CheckInput(input).ConfigureAwait(false);//检查参数
if (type == ItemChangedType.Add)
{
if (!((await SysUserService.GetUserByIdAsync(UserManager.UserId).ConfigureAwait(false)).IsGlobal))
{
input.Category = RoleCategoryEnum.Org;
}
}
else
{
await SysUserService.CheckApiDataScopeAsync(input.OrgId, input.CreateUserId).ConfigureAwait(false);
}
if (await base.SaveAsync(input, type).ConfigureAwait(false))
{
RefreshCache();
await ClearTokenUtil.DeleteUserCacheByRoleIds(new List<long> { input.Id }).ConfigureAwait(false);//清除角色下用户缓存
return true;
}
return false;
}
#endregion
#region
#region
/// <summary>
/// 获取拥有的资源
/// </summary>
/// <param name="id">id</param>
/// <param name="category">类型</param>
public async Task<GrantResourceData> OwnResourceAsync(long id, RelationCategoryEnum category = RelationCategoryEnum.RoleHasResource)
{
var roleOwnResource = new GrantResourceData() { Id = id };//定义结果集
//获取关系列表
var relations = await _relationService.GetRelationListByObjectIdAndCategoryAsync(id, category).ConfigureAwait(false);
roleOwnResource.GrantInfoList = relations.Select(it => (it.ExtJson?.FromJsonNetString<RelationResourcePermission?>())).Where(a => a != null);
return roleOwnResource;
}
/// <summary>
/// 授权资源
/// </summary>
/// <param name="input">授权信息</param>
[OperDesc("RoleGrantResource")]
public async Task GrantResourceAsync(GrantResourceData input)
{
var isSuperAdmin = input.Id == RoleConst.SuperAdminRoleId;//判断是否有超管
if (isSuperAdmin)
throw Oops.Bah(Localizer["CanotGrantAdmin"]);
var menuIds = input.GrantInfoList.Select(it => it.MenuId).ToList();//菜单ID
2025-05-20 23:21:58 +08:00
var extJsons = input.GrantInfoList.Select(it => it.ToSystemTextJsonString()).ToList();//拓展信息
2025-01-24 22:42:26 +08:00
var relationRoles = new List<SysRelation>();//要添加的角色资源和授权关系表
var sysRole = (await GetAllAsync().ConfigureAwait(false)).FirstOrDefault(it => it.Id == input.Id);//获取角色
await SysUserService.CheckApiDataScopeAsync(sysRole.OrgId, sysRole.CreateUserId).ConfigureAwait(false);
if (sysRole != null)
{
var resources = await _sysResourceService.GetAllAsync().ConfigureAwait(false);
var menusList = resources.Where(a => a.Category == ResourceCategoryEnum.Menu).Where(a => menuIds.Contains(a.Id));
#region
//获取我的模块信息Id列表
var moduleIds = menusList.Select(it => it.Module).Distinct();
foreach (var item in moduleIds)
{
//将角色资源添加到列表
relationRoles.Add(new SysRelation
{
ObjectId = sysRole.Id,
TargetId = item.ToString(),
Category = RelationCategoryEnum.RoleHasModule
});
}
#endregion
#region
//遍历菜单列表
for (var i = 0; i < menuIds.Count; i++)
{
//将角色资源添加到列表
relationRoles.Add(new SysRelation
{
ObjectId = sysRole.Id,
TargetId = menuIds[i].ToString(),
Category = RelationCategoryEnum.RoleHasResource,
ExtJson = extJsons?[i]
});
}
#endregion
#region .
var defaultDataScope = sysRole.DefaultDataScope;//获取默认数据范围
2025-07-24 19:46:30 +08:00
if (relationRoles.Count != 0)
2025-01-24 22:42:26 +08:00
{
//获取权限授权树
var permissions = App.GetService<IApiPermissionService>().PermissionTreeSelector(menusList.Select(it => it.Href));
//要添加的角色有哪些权限列表
var relationRolePer = permissions.Select(it => new SysRelation
{
ObjectId = sysRole.Id,
TargetId = it.ApiRoute,
Category = RelationCategoryEnum.RoleHasPermission,
ExtJson = new RelationPermission
{
ApiUrl = it.ApiRoute,
2025-05-20 23:21:58 +08:00
}.ToSystemTextJsonString()
2025-01-24 22:42:26 +08:00
});
relationRoles.AddRange(relationRolePer);//合并列表
}
#endregion .
#region
using var db = GetDB();
//事务
var result = await db.UseTranAsync(async () =>
{
await db.Deleteable<SysRelation>(it =>
it.ObjectId == sysRole.Id && (it.Category == RelationCategoryEnum.RoleHasPermission || it.Category == RelationCategoryEnum.RoleHasResource
|| it.Category == RelationCategoryEnum.RoleHasModule
)).ExecuteCommandAsync().ConfigureAwait(false);
await db.Insertable(relationRoles).ExecuteCommandAsync().ConfigureAwait(false);//添加新的
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
_relationService.RefreshCache(RelationCategoryEnum.RoleHasResource);//刷新关系缓存
_relationService.RefreshCache(RelationCategoryEnum.RoleHasPermission);//刷新关系缓存
_relationService.RefreshCache(RelationCategoryEnum.RoleHasModule);//关系表刷新
await ClearTokenUtil.DeleteUserCacheByRoleIds(new List<long> { input.Id }).ConfigureAwait(false);//清除角色下用户缓存
}
else
{
throw new(result.ErrorMessage, result.ErrorException);
}
#endregion
}
}
#endregion
#region OPENAPI
/// <summary>
/// 获取角色拥有的OpenApi权限
/// </summary>
/// <param name="id">角色id</param>
public async Task<GrantPermissionData> ApiOwnPermissionAsync(long id)
{
var roleOwnPermission = new GrantPermissionData { Id = id };//定义结果集
//获取关系列表
var relations = await _relationService.GetRelationListByObjectIdAndCategoryAsync(id, RelationCategoryEnum.RoleHasOpenApiPermission).ConfigureAwait(false);
roleOwnPermission.GrantInfoList = relations.Select(it => it.ExtJson?.FromJsonNetString<RelationPermission>()!).Where(a => a != null);
return roleOwnPermission;
}
/// <summary>
/// 授权OpenApi权限
/// </summary>
/// <param name="input">授权信息</param>
[OperDesc("RoleGrantApiPermission")]
public async Task GrantApiPermissionAsync(GrantPermissionData input)
{
var isSuperAdmin = input.Id == RoleConst.SuperAdminRoleId;//判断是否有超管
if (isSuperAdmin)
throw Oops.Bah(Localizer["CanotGrantAdmin"]);
var sysRole = (await GetAllAsync().ConfigureAwait(false)).FirstOrDefault(it => it.Id == input.Id);//获取角色
await SysUserService.CheckApiDataScopeAsync(sysRole.OrgId, sysRole.CreateUserId).ConfigureAwait(false);
if (sysRole != null)
{
await _relationService.SaveRelationBatchAsync(RelationCategoryEnum.RoleHasOpenApiPermission, input.Id,
2025-05-20 23:21:58 +08:00
input.GrantInfoList.Select(a => (a.ApiUrl, a.ToSystemTextJsonString()))
2025-01-24 22:42:26 +08:00
, true).ConfigureAwait(false);//添加到数据库
await ClearTokenUtil.DeleteUserCacheByRoleIds(new List<long> { input.Id }).ConfigureAwait(false);//清除角色下用户缓存
}
}
#endregion OPENAPI
#region
/// <inheritdoc/>
public async Task<IEnumerable<long>> OwnUserAsync(long id)
{
//获取关系列表
var relations = await _relationService.GetRelationListByTargetIdAndCategoryAsync(id.ToString(), RelationCategoryEnum.UserHasRole).ConfigureAwait(false);
return relations.Select(it => it.ObjectId);
}
/// <summary>
/// 授权用户
/// </summary>
/// <param name="input">授权参数</param>
[OperDesc("RoleGrantUser")]
public async Task GrantUserAsync(GrantUserOrRoleInput input)
{
var isSuperAdmin = input.Id == RoleConst.SuperAdminRoleId;//判断是否有超管
if (isSuperAdmin)
throw Oops.Bah(Localizer["CanotGrantAdmin"]);
var sysRole = (await GetAllAsync().ConfigureAwait(false)).FirstOrDefault(a => a.Id == input.Id);
await SysUserService.CheckApiDataScopeAsync(sysRole.OrgId, sysRole.CreateUserId).ConfigureAwait(false);
var sysRelations = input.GrantInfoList.Select(it =>
new SysRelation()
{
ObjectId = it,
TargetId = input.Id.ToString(),
Category = RelationCategoryEnum.UserHasRole
}
);
using var db = GetDB();
//事务
var result = await db.UseTranAsync(async () =>
{
var targetId = input.Id.ToString();
await db.Deleteable<SysRelation>(it => it.TargetId == targetId && it.Category == RelationCategoryEnum.UserHasRole).ExecuteCommandAsync().ConfigureAwait(false);//删除老的
await db.Insertable(sysRelations.ToList()).ExecuteCommandAsync().ConfigureAwait(false);//添加新的
}).ConfigureAwait(false);
if (result.IsSuccess)//如果成功了
{
_relationService.RefreshCache(RelationCategoryEnum.UserHasRole);//刷新关系表UserHasRole缓存
await ClearTokenUtil.DeleteUserCacheByRoleIds(new List<long> { input.Id }).ConfigureAwait(false);//清除角色下用户缓存
}
else
{
throw new(result.ErrorMessage, result.ErrorException);
}
}
#endregion
/// <inheritdoc/>
public void RefreshCache()
{
App.CacheService.Remove(CacheConst.Cache_SysRole);//删除KEY
_dispatchService.Dispatch(null);
}
#endregion
#region
/// <summary>
/// 检查输入参数
/// </summary>
/// <param name="sysRole"></param>
private async Task CheckInput(SysRole sysRole)
{
if (sysRole.Id == RoleConst.SuperAdminRoleId)
throw Oops.Bah(Localizer["CanotEditAdmin"]);
if (sysRole.Category == RoleCategoryEnum.Org && sysRole.OrgId == 0)
throw Oops.Bah(Localizer["OrgNotNull"]);
if (sysRole.Category == RoleCategoryEnum.Global)//如果是全局
sysRole.OrgId = 0;//机构id设0
var sysRoles = await GetAllAsync().ConfigureAwait(false);//获取所有
var repeatName = sysRoles.Any(it => it.OrgId == sysRole.OrgId && it.Name == sysRole.Name && it.Id != sysRole.Id);//是否有重复角色名称
if (repeatName)//如果有
{
if (sysRole.OrgId == 0)
throw Oops.Bah(Localizer["SameOrgNameDup", sysRole.Name]);
throw Oops.Bah(Localizer["NameDup", sysRole.Name]);
}
if (!((await GetRoleListByUserIdAsync(UserManager.UserId).ConfigureAwait(false)).Any(a => a.Category == RoleCategoryEnum.Global)) && sysRole.DefaultDataScope.ScopeCategory == DataScopeEnum.SCOPE_ALL)
throw Oops.Bah(Localizer["CannotRoleScopeAll"]);
//如果code没填
if (string.IsNullOrEmpty(sysRole.Code))
{
sysRole.Code = RandomHelper.CreateRandomString(10);//赋值Code
}
//判断是否有相同的Code
if (sysRoles.Any(it => it.Code == sysRole.Code && it.Id != sysRole.Id))
throw Oops.Bah(Localizer["CodeDup", sysRole.Code]);
}
#endregion
}