You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
8.3 KiB
215 lines
8.3 KiB
using Microsoft.AspNetCore.Authorization; |
|
using Microsoft.Extensions.Options; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Threading.Tasks; |
|
using Volo.Abp; |
|
using Volo.Abp.Application.Services; |
|
using Volo.Abp.Authorization; |
|
using Volo.Abp.MultiTenancy; |
|
using Volo.Abp.PermissionManagement; |
|
using Volo.Abp.Security.Claims; |
|
|
|
namespace Sanhe.Abp.MenuManagement |
|
{ |
|
[Authorize] |
|
public class MenuGrantAppService : ApplicationService, IMenuGrantAppService |
|
{ |
|
private readonly IAbpAuthorizationPolicyProvider _abpAuthorizationPolicyProvider; |
|
private readonly IUserMenuGrantChecker _userMenuGrantChecker; |
|
private readonly ICurrentPrincipalAccessor _principalAccessor; |
|
private readonly IAuthorizationService _authorizationService; |
|
private readonly IMenuManager _menuManager; |
|
private readonly IMenuAppService _menuAppService; |
|
private readonly IMenuRepository _menuRepository; |
|
private readonly PermissionManagementOptions _options; |
|
private readonly IPermissionAppService _permissionAppService; |
|
|
|
public MenuGrantAppService( |
|
IMenuRepository menuRepository, |
|
IMenuManager menuManager, |
|
IMenuAppService menuAppService, |
|
IPermissionAppService permissionAppService, |
|
IOptions<PermissionManagementOptions> options, |
|
IAuthorizationService authorizationService, |
|
IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider, |
|
IUserMenuGrantChecker userMenuGrantChecker, |
|
ICurrentPrincipalAccessor principalAccessor |
|
) |
|
{ |
|
_menuRepository = menuRepository; |
|
_menuManager = menuManager; |
|
_menuAppService = menuAppService; |
|
_permissionAppService = permissionAppService; |
|
_authorizationService = authorizationService; |
|
_abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider; |
|
_userMenuGrantChecker = userMenuGrantChecker; |
|
_principalAccessor = principalAccessor; |
|
_options = options.Value; |
|
} |
|
|
|
public virtual async Task<GetMenuResultDto> GetListAsync() |
|
{ |
|
var queryable = await _menuRepository.GetQueryableAsync(); |
|
var rootMenus = queryable.Where( |
|
x => x.MenuType == MenuEnumType.Menu |
|
) |
|
.OrderBy(x => x.Sort) |
|
.ToList() |
|
.Where(x => !x.ParentId.HasValue).ToList(); // 根节点 |
|
|
|
var menuDtos = new List<FrontMenu>(); |
|
foreach (var menu in rootMenus) |
|
{ |
|
var isGranted = await _userMenuGrantChecker.CheckAsync(_principalAccessor.Principal, menu); |
|
if (isGranted) |
|
{ |
|
var dto = ObjectMapper.Map<Menu, FrontMenu>(menu); |
|
menuDtos.Add(dto); |
|
await FilterChildrenMenuRecursivelyAsync(menu, dto); |
|
} |
|
} |
|
|
|
var permissionGrants = new List<string>(); |
|
var policyNames = await _abpAuthorizationPolicyProvider.GetPoliciesNamesAsync(); |
|
foreach (var policyName in policyNames) |
|
{ |
|
if (await _authorizationService.IsGrantedAsync(policyName)) |
|
{ |
|
permissionGrants.Add(policyName); |
|
} |
|
} |
|
|
|
return new GetMenuResultDto |
|
{ |
|
Menus = menuDtos, |
|
PermissionGrants = permissionGrants |
|
}; |
|
} |
|
|
|
public virtual async Task<GetMenuGrantListResultDto> GetAsync(string providerName, string providerKey) |
|
{ |
|
await CheckProviderPolicy(providerName); |
|
return await InternalGetAsync(providerName, providerKey); |
|
} |
|
|
|
public virtual async Task UpdateAsync(string providerName, string providerKey, UpdateMenuGrantsDto input) |
|
{ |
|
await CheckProviderPolicy(providerName); |
|
|
|
foreach (var grantDto in input.Menus) |
|
{ |
|
await _menuManager.SetAsync(grantDto.Id, providerName, providerKey, grantDto.IsGranted); |
|
} |
|
|
|
var permissions = _menuManager.GetPermissions(providerName); |
|
var updatePermissionDtos = permissions |
|
.Select(x => |
|
{ |
|
var menuDto = input.Menus.FirstOrDefault(y => y.PermissionKey == x.Name); |
|
var dto = new UpdatePermissionDto |
|
{ |
|
Name = x.Name, |
|
IsGranted = menuDto?.IsGranted ?? true // 默认给予授权,如果菜单与权限绑定,则以菜单的授权为主。 |
|
}; |
|
|
|
return dto; |
|
}) |
|
.ToArray(); |
|
|
|
await _permissionAppService.UpdateAsync( |
|
providerName, |
|
providerKey, |
|
new UpdatePermissionsDto |
|
{ |
|
Permissions = updatePermissionDtos |
|
} |
|
); |
|
} |
|
|
|
private async Task<GetMenuGrantListResultDto> InternalGetAsync(string providerName, string providerKey) |
|
{ |
|
var allMenus = (await _menuRepository.GetQueryableAsync()).ToList(); |
|
var multiTenancySide = CurrentTenant.GetMultiTenancySide(); |
|
|
|
var menuGrants = new List<MenuGrantInfoDto>(); |
|
|
|
foreach (var menu in allMenus) |
|
{ |
|
if (!menu.MultiTenancySide.HasFlag(multiTenancySide)) |
|
{ |
|
continue; |
|
} |
|
|
|
var grantInfo = await _menuManager.GetAsync(menu.Id, providerName, providerKey); |
|
menuGrants.Add(new MenuGrantInfoDto |
|
{ |
|
Id = menu.Id, |
|
Name = menu.Name, |
|
DisplayName = menu.DisplayName, |
|
PermissionKey = menu.PermissionKey, |
|
IsGranted = grantInfo.IsGranted, |
|
GrantedProviders = grantInfo.Providers |
|
}); |
|
} |
|
|
|
// _menuAppService.GetListAsync 没有做租户过滤,所以 这里要根据当前用户租户过滤。 |
|
var menuDtos = new List<MenuDto>(); |
|
foreach (var menu in (await _menuAppService.GetListAsync(new MenuRequestDto())).Items) |
|
{ |
|
if (menu.MultiTenancySide.HasFlag(multiTenancySide)) |
|
{ |
|
menuDtos.Add(menu); |
|
FilterChildrenByTenancySide(menu, multiTenancySide); |
|
} |
|
} |
|
|
|
return new GetMenuGrantListResultDto |
|
{ |
|
MenuGrants = menuGrants, |
|
Menus = menuDtos |
|
}; |
|
} |
|
|
|
private void FilterChildrenByTenancySide(MenuDto menuDto, MultiTenancySides multiTenancySides) |
|
{ |
|
if (menuDto.Children?.Count > 0) |
|
{ |
|
menuDto.Children = menuDto.Children.Where(x => x.MultiTenancySide.HasFlag(multiTenancySides)).ToList(); |
|
foreach (var child in menuDto.Children) |
|
{ |
|
FilterChildrenByTenancySide(child, multiTenancySides); |
|
} |
|
} |
|
} |
|
|
|
private async Task CheckProviderPolicy(string providerName) |
|
{ |
|
var policyName = _options.ProviderPolicies.GetOrDefault(providerName); |
|
if (policyName.IsNullOrEmpty()) |
|
{ |
|
throw new AbpException($"No policy defined to get/set permissions for the provider '{policyName}'. Use {nameof(PermissionManagementOptions)} to map the policy."); |
|
} |
|
|
|
await AuthorizationService.CheckAsync(policyName); |
|
} |
|
|
|
private async Task FilterChildrenMenuRecursivelyAsync(Menu parent, FrontMenu vueMenu) |
|
{ |
|
if (parent.Children != null) |
|
{ |
|
vueMenu.Children = new List<FrontMenu>(); |
|
foreach (var menu in parent.Children) |
|
{ |
|
if (await _userMenuGrantChecker.CheckAsync(_principalAccessor.Principal, menu)) |
|
{ |
|
var dto = ObjectMapper.Map<Menu, FrontMenu>(menu); |
|
vueMenu.Children.Add(dto); |
|
await FilterChildrenMenuRecursivelyAsync(menu, dto); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |