|
@@ -86,7 +86,10 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|
|
[DisplayName("增加角色")]
|
|
[DisplayName("增加角色")]
|
|
|
public async Task AddRole(AddRoleInput input)
|
|
public async Task AddRole(AddRoleInput input)
|
|
|
{
|
|
{
|
|
|
- if (await _sysRoleRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code))
|
|
|
|
|
|
|
+ // 角色唯一性以租户为界:同租户内不允许 名称+编码 重复,跨租户允许复用
|
|
|
|
|
+ // 租户Id取最终落库值(未指定时 SqlSugar 插入过滤器会回填当前登录租户),保证校验范围与写入范围一致
|
|
|
|
|
+ long? tenantId = input.TenantId is > 0 ? input.TenantId : _userManager.TenantId;
|
|
|
|
|
+ if (await _sysRoleRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.TenantId == tenantId))
|
|
|
throw Oops.Oh(ErrorCodeEnum.D1006);
|
|
throw Oops.Oh(ErrorCodeEnum.D1006);
|
|
|
|
|
|
|
|
var newRole = await _sysRoleRep.AsInsertable(input.Adapt<SysRole>()).ExecuteReturnEntityAsync();
|
|
var newRole = await _sysRoleRep.AsInsertable(input.Adapt<SysRole>()).ExecuteReturnEntityAsync();
|
|
@@ -101,11 +104,12 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|
|
/// <returns></returns>
|
|
/// <returns></returns>
|
|
|
private async Task UpdateRoleMenu(AddRoleInput input)
|
|
private async Task UpdateRoleMenu(AddRoleInput input)
|
|
|
{
|
|
{
|
|
|
- if (input.MenuIdList == null || input.MenuIdList.Count < 1) return;
|
|
|
|
|
|
|
+ // 空集合(或 null)语义为“该角色最终不拥有任何菜单”,而非“不修改菜单”,
|
|
|
|
|
+ // 因此必须继续下发以删除既有授权,不能在此提前返回
|
|
|
await GrantMenu(new RoleMenuInput()
|
|
await GrantMenu(new RoleMenuInput()
|
|
|
{
|
|
{
|
|
|
Id = input.Id,
|
|
Id = input.Id,
|
|
|
- MenuIdList = input.MenuIdList.ToList()
|
|
|
|
|
|
|
+ MenuIdList = input.MenuIdList?.ToList() ?? new List<long>()
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -118,7 +122,10 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|
|
[DisplayName("更新角色")]
|
|
[DisplayName("更新角色")]
|
|
|
public async Task UpdateRole(UpdateRoleInput input)
|
|
public async Task UpdateRole(UpdateRoleInput input)
|
|
|
{
|
|
{
|
|
|
- if (await _sysRoleRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.Id != input.Id))
|
|
|
|
|
|
|
+ // 角色唯一性以租户为界:同租户内不允许 名称+编码 重复,跨租户允许复用
|
|
|
|
|
+ // 租户Id标记了 IsOnlyIgnoreUpdate(更新时不落库、不可迁移租户),故以库中现有值为准,不采信入参
|
|
|
|
|
+ var tenantId = await _sysRoleRep.AsQueryable().Where(u => u.Id == input.Id).Select(u => u.TenantId).FirstAsync();
|
|
|
|
|
+ if (await _sysRoleRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.TenantId == tenantId && u.Id != input.Id))
|
|
|
throw Oops.Oh(ErrorCodeEnum.D1006);
|
|
throw Oops.Oh(ErrorCodeEnum.D1006);
|
|
|
|
|
|
|
|
await _sysRoleRep.AsUpdateable(input.Adapt<SysRole>()).IgnoreColumns(true)
|
|
await _sysRoleRep.AsUpdateable(input.Adapt<SysRole>()).IgnoreColumns(true)
|
|
@@ -167,7 +174,8 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|
|
[DisplayName("授权角色菜单")]
|
|
[DisplayName("授权角色菜单")]
|
|
|
public async Task GrantMenu(RoleMenuInput input)
|
|
public async Task GrantMenu(RoleMenuInput input)
|
|
|
{
|
|
{
|
|
|
- if (input.MenuIdList == null || input.MenuIdList.Count < 1) return;
|
|
|
|
|
|
|
+ // 空集合语义为“清空该角色全部菜单授权”,交由 GrantRoleMenu 先删后插(删除无条件、插入按需)
|
|
|
|
|
+ input.MenuIdList ??= new List<long>();
|
|
|
|
|
|
|
|
await ClearUserApiCache(input.Id);
|
|
await ClearUserApiCache(input.Id);
|
|
|
|
|
|