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, IMenuAppService { private readonly IPermissionDefinitionManager _permissionDefinitionManager; private readonly IMenuManager _menuManager; private readonly IStringLocalizerFactory _stringLocalizerFactory; public MenuAppService( IRepository 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 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> GetAuthPolicies() { var result = new List(); 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 { 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 CreateAsync(CreateOrUpdateMenuDto input) { await PermissionChecker(input.PermissionKey); return await base.CreateAsync(input); } public override async Task> 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(); foreach (var menu in root) { var dto = ObjectMapper.Map(menu); menuDtos.Add(dto); // AddChildrenMenuRecursively(dto, allMenus); SortChildrenMenu(dto); } return new PagedResultDto(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 allMenus) { foreach (var menu in allMenus.Where(x => x.ParentId == parent.Id).OrderBy(x => x.Sort)) { var dto = ObjectMapper.Map(menu); parent.Children.Add(dto); AddChildrenMenuRecursively(dto, allMenus); } } } }