Abp模块
abp
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

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);
}
}
}
}
}
}