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.
182 lines
7.0 KiB
182 lines
7.0 KiB
3 years ago
|
using Microsoft.AspNetCore.Authorization;
|
||
|
using Microsoft.Extensions.Localization;
|
||
|
using Sanhe.Abp.MenuManagement.Permissions;
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Threading.Tasks;
|
||
|
using Volo.Abp;
|
||
|
using Volo.Abp.Application.Dtos;
|
||
|
using Volo.Abp.Application.Services;
|
||
|
using Volo.Abp.Authorization.Permissions;
|
||
|
using Volo.Abp.Domain.Repositories;
|
||
|
using Volo.Abp.MultiTenancy;
|
||
|
|
||
|
namespace Sanhe.Abp.MenuManagement
|
||
|
{
|
||
|
[Authorize]
|
||
|
public class MenuAppService : CrudAppService<Menu, MenuDto, Guid, MenuRequestDto, CreateOrUpdateMenuDto, CreateOrUpdateMenuDto>,
|
||
|
IMenuAppService
|
||
|
{
|
||
|
private readonly IPermissionDefinitionManager _permissionDefinitionManager;
|
||
|
private readonly IMenuManager _menuManager;
|
||
|
private readonly IStringLocalizerFactory _stringLocalizerFactory;
|
||
|
|
||
|
public MenuAppService(
|
||
|
IRepository<Menu, Guid> repository,
|
||
|
IPermissionDefinitionManager permissionDefinitionManager,
|
||
|
IMenuManager menuManager,
|
||
|
IStringLocalizerFactory stringLocalizerFactory
|
||
|
) : base(repository)
|
||
|
{
|
||
|
_permissionDefinitionManager = permissionDefinitionManager;
|
||
|
_menuManager = menuManager;
|
||
|
_stringLocalizerFactory = stringLocalizerFactory;
|
||
|
}
|
||
|
|
||
|
protected override string GetListPolicyName => MenuManagementPermissions.Menus.Default;
|
||
|
protected override string CreatePolicyName => MenuManagementPermissions.Menus.Create;
|
||
|
protected override string UpdatePolicyName => MenuManagementPermissions.Menus.Update;
|
||
|
protected override string DeletePolicyName => MenuManagementPermissions.Menus.Delete;
|
||
|
|
||
|
public override async Task<MenuDto> UpdateAsync(Guid id, CreateOrUpdateMenuDto input)
|
||
|
{
|
||
|
await PermissionChecker(input.PermissionKey, id);
|
||
|
|
||
|
// 当更新菜单权限时,同时刷 PermissionGrant
|
||
|
var menu = await GetEntityByIdAsync(id);
|
||
|
if (menu.PermissionKey != input.PermissionKey)
|
||
|
{
|
||
|
await _menuManager.UpdatePermissionGrantAsync(id, menu.PermissionKey, input.PermissionKey);
|
||
|
}
|
||
|
|
||
|
return await base.UpdateAsync(id, input);
|
||
|
}
|
||
|
|
||
|
public virtual Task<List<AuthPolicyDto>> GetAuthPolicies()
|
||
|
{
|
||
|
var result = new List<AuthPolicyDto>();
|
||
|
var groups = _permissionDefinitionManager.GetGroups();
|
||
|
var multiTenancySide = CurrentTenant.GetMultiTenancySide();
|
||
|
foreach (var group in groups)
|
||
|
{
|
||
|
if (group.Permissions.Count == 0)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
foreach (var permission in group.Permissions)
|
||
|
{
|
||
|
if (multiTenancySide != MultiTenancySides.Host &&
|
||
|
!permission.MultiTenancySide.HasFlag(multiTenancySide))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
var policy = new AuthPolicyDto()
|
||
|
{
|
||
|
Name = permission.Name,
|
||
|
DisplayName = permission.DisplayName.Localize(_stringLocalizerFactory),
|
||
|
Children = new List<AuthPolicyDto>
|
||
|
{
|
||
|
new AuthPolicyDto
|
||
|
{
|
||
|
Name = permission.Name,
|
||
|
DisplayName = permission.DisplayName.Localize(_stringLocalizerFactory)
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
result.Add(policy);
|
||
|
|
||
|
foreach (var c in permission.Children)
|
||
|
{
|
||
|
if (multiTenancySide != MultiTenancySides.Host &&
|
||
|
!c.MultiTenancySide.HasFlag(multiTenancySide))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
policy.Children.Add(new AuthPolicyDto
|
||
|
{
|
||
|
Name = c.Name,
|
||
|
DisplayName = c.DisplayName.Localize(_stringLocalizerFactory)
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Task.FromResult(result);
|
||
|
}
|
||
|
|
||
|
public override async Task<MenuDto> CreateAsync(CreateOrUpdateMenuDto input)
|
||
|
{
|
||
|
await PermissionChecker(input.PermissionKey);
|
||
|
return await base.CreateAsync(input);
|
||
|
}
|
||
|
|
||
|
public override async Task<PagedResultDto<MenuDto>> GetListAsync(MenuRequestDto input)
|
||
|
{
|
||
|
//await CheckGetListPolicyAsync();
|
||
|
var queryable = await Repository.GetQueryableAsync();
|
||
|
var allMenus = queryable
|
||
|
.WhereIf(input.Type.HasValue, m => m.MenuType == input.Type)
|
||
|
.WhereIf(!input.Name.IsNullOrWhiteSpace(), m => m.DisplayName.Contains(input.Name))
|
||
|
.ToList();
|
||
|
|
||
|
var root = allMenus
|
||
|
.Where(x => !x.ParentId.HasValue) // 没有parentId
|
||
|
.Union(
|
||
|
// 有parentId,但是“allMenus"中不存在他的Parent。
|
||
|
allMenus.Where(x => x.ParentId.HasValue).Where(x => allMenus.All(y => x.ParentId != y.Id))
|
||
|
)
|
||
|
.OrderBy(x => x.Sort);
|
||
|
|
||
|
var menuDtos = new List<MenuDto>();
|
||
|
foreach (var menu in root)
|
||
|
{
|
||
|
var dto = ObjectMapper.Map<Menu, MenuDto>(menu);
|
||
|
menuDtos.Add(dto);
|
||
|
// AddChildrenMenuRecursively(dto, allMenus);
|
||
|
|
||
|
SortChildrenMenu(dto);
|
||
|
}
|
||
|
|
||
|
return new PagedResultDto<MenuDto>(allMenus.Count, menuDtos);
|
||
|
}
|
||
|
|
||
|
private async Task PermissionChecker(string permissionName, Guid? menuId = null)
|
||
|
{
|
||
|
if (!permissionName.IsNullOrWhiteSpace())
|
||
|
{
|
||
|
var permission = _permissionDefinitionManager.GetOrNull(permissionName);
|
||
|
if (permission == null)
|
||
|
{
|
||
|
throw new UserFriendlyException($"未知的权限:“{permissionName}”。");
|
||
|
}
|
||
|
|
||
|
var menu = await Repository.FirstOrDefaultAsync(x => x.PermissionKey == permissionName && x.Id != menuId);
|
||
|
if (menu != null)
|
||
|
{
|
||
|
throw new UserFriendlyException($"权限已经被菜单“{menu.DisplayName}”绑定。");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void SortChildrenMenu(MenuDto dto)
|
||
|
{
|
||
|
dto.Children.Sort((a, b) => string.Compare(a.Sort, b.Sort, StringComparison.Ordinal));
|
||
|
dto.Children.ForEach(SortChildrenMenu);
|
||
|
}
|
||
|
|
||
|
private void AddChildrenMenuRecursively(MenuDto parent, List<Menu> allMenus)
|
||
|
{
|
||
|
foreach (var menu in allMenus.Where(x => x.ParentId == parent.Id).OrderBy(x => x.Sort))
|
||
|
{
|
||
|
var dto = ObjectMapper.Map<Menu, MenuDto>(menu);
|
||
|
parent.Children.Add(dto);
|
||
|
|
||
|
AddChildrenMenuRecursively(dto, allMenus);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|