83 changed files with 2654 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||||
|
</Weavers> |
@ -0,0 +1,21 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||||
|
<Import Project="..\..\..\common.props" /> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||||
|
<RootNamespace /> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.Authorization" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.Application.Contracts" Version="$(VoloAbpVersion)" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<ProjectReference Include="..\Sanhe.Abp.MenuManagement.Domain.Shared\Sanhe.Abp.MenuManagement.Domain.Shared.csproj" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
</Project> |
@ -0,0 +1,23 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 授权策略 |
||||||
|
/// </summary> |
||||||
|
public class AuthPolicyDto |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 名称 |
||||||
|
/// </summary> |
||||||
|
public string Name { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 显示名称 |
||||||
|
/// </summary> |
||||||
|
public string DisplayName { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 子策略 |
||||||
|
/// </summary> |
||||||
|
public List<AuthPolicyDto> Children { get; set; } = new List<AuthPolicyDto>(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.ComponentModel.DataAnnotations; |
||||||
|
using Volo.Abp.Application.Dtos; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 创建修改菜单 |
||||||
|
/// </summary> |
||||||
|
public class CreateOrUpdateMenuDto : EntityDto, IValidatableObject |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 名称 |
||||||
|
/// </summary> |
||||||
|
public string Name { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 显示名称 |
||||||
|
/// </summary> |
||||||
|
public string DisplayName { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 组件路径 |
||||||
|
/// </summary> |
||||||
|
public string ComponentPath { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 路由路径 |
||||||
|
/// </summary> |
||||||
|
public string RouterPath { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 父Id |
||||||
|
/// </summary> |
||||||
|
public Guid? ParentId { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 菜单类型 |
||||||
|
/// </summary> |
||||||
|
public MenuEnumType MenuType { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 图标 |
||||||
|
/// </summary> |
||||||
|
public string Icon { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 排序 |
||||||
|
/// </summary> |
||||||
|
public string Sort { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// window.open _blank |
||||||
|
/// </summary> |
||||||
|
public string TargetUrl { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 此菜单关联的权限key |
||||||
|
/// </summary> |
||||||
|
public string PermissionKey { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 表示多租户应用程序中的所属方 |
||||||
|
/// </summary> |
||||||
|
public MultiTenancySides MultiTenancySide { get; set; } |
||||||
|
|
||||||
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) |
||||||
|
{ |
||||||
|
if (MenuType == MenuEnumType.Menu) |
||||||
|
{ |
||||||
|
if (Name.IsNullOrWhiteSpace()) |
||||||
|
{ |
||||||
|
yield return new ValidationResult("Name 不能为空", new[] { "Name" }); |
||||||
|
} |
||||||
|
|
||||||
|
if (DisplayName.IsNullOrWhiteSpace()) |
||||||
|
{ |
||||||
|
yield return new ValidationResult("DisplayName 不能为空", new[] { "DisplayName" }); |
||||||
|
} |
||||||
|
|
||||||
|
if (RouterPath.IsNullOrWhiteSpace()) |
||||||
|
{ |
||||||
|
yield return new ValidationResult("RouterPath 不能为空", new[] { "RouterPath" }); |
||||||
|
} |
||||||
|
|
||||||
|
if (ComponentPath.IsNullOrWhiteSpace()) |
||||||
|
{ |
||||||
|
yield return new ValidationResult("ComponentPath 不能为空", new[] { "ComponentPath" }); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (MenuType == MenuEnumType.Permission) |
||||||
|
{ |
||||||
|
if (DisplayName.IsNullOrWhiteSpace()) |
||||||
|
{ |
||||||
|
yield return new ValidationResult("DisplayName 不能为空", new[] { "DisplayName" }); |
||||||
|
} |
||||||
|
|
||||||
|
if (!ParentId.HasValue) |
||||||
|
{ |
||||||
|
yield return new ValidationResult("ParentId 不能为空", new[] { "ParentId" }); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 前端菜单 |
||||||
|
/// </summary> |
||||||
|
public class FrontMenu |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Id |
||||||
|
/// </summary> |
||||||
|
public Guid Id { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 名称 |
||||||
|
/// </summary> |
||||||
|
public string Name { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 组件 |
||||||
|
/// </summary> |
||||||
|
public string Component { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 路径 |
||||||
|
/// </summary> |
||||||
|
public string Path { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// window.open _blank |
||||||
|
/// </summary> |
||||||
|
public string TargetUrl { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 此菜单关联的权限key. |
||||||
|
/// </summary> |
||||||
|
public string PermissionKey { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 菜单标签 |
||||||
|
/// </summary> |
||||||
|
public MenuMeta Meta { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 子菜单 |
||||||
|
/// </summary> |
||||||
|
public List<FrontMenu> Children { get; set; } = new List<FrontMenu>(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class GetMenuGrantListResultDto |
||||||
|
{ |
||||||
|
public List<MenuGrantInfoDto> MenuGrants { get; set; } |
||||||
|
public List<MenuDto> Menus { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class GetMenuResultDto |
||||||
|
{ |
||||||
|
public List<string> PermissionGrants { get; set; } |
||||||
|
public List<FrontMenu> Menus { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Application.Services; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IMenuAppService : ICrudAppService<MenuDto, Guid, MenuRequestDto, CreateOrUpdateMenuDto> |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 获取授权策略 |
||||||
|
/// </summary> |
||||||
|
/// <returns></returns> |
||||||
|
Task<List<AuthPolicyDto>> GetAuthPolicies(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
using JetBrains.Annotations; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Application.Services; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IMenuGrantAppService : IApplicationService |
||||||
|
{ |
||||||
|
Task<GetMenuResultDto> GetListAsync(); |
||||||
|
Task<GetMenuGrantListResultDto> GetAsync([NotNull] string providerName, [NotNull] string providerKey); |
||||||
|
Task UpdateAsync([NotNull] string providerName, [NotNull] string providerKey, UpdateMenuGrantsDto input); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using Volo.Abp.Application.Dtos; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuDto : AuditedEntityDto<Guid> |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 名称 |
||||||
|
/// </summary> |
||||||
|
public string Name { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 显示名称 |
||||||
|
/// </summary> |
||||||
|
public string DisplayName { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 菜单类型 |
||||||
|
/// </summary> |
||||||
|
public MenuEnumType MenuType { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 组件路径 |
||||||
|
/// </summary> |
||||||
|
public string ComponentPath { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 路由路径 |
||||||
|
/// </summary> |
||||||
|
public string RouterPath { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 父级显示名称 |
||||||
|
/// </summary> |
||||||
|
public string ParentDisplayName { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 父Id |
||||||
|
/// </summary> |
||||||
|
public Guid? ParentId { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 图标 |
||||||
|
/// </summary> |
||||||
|
public string Icon { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 排序 |
||||||
|
/// </summary> |
||||||
|
public string Sort { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// window.open _blank |
||||||
|
/// </summary> |
||||||
|
public string TargetUrl { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 此菜单关联的权限key |
||||||
|
/// </summary> |
||||||
|
public string PermissionKey { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 表示多租户应用程序中的所属方 |
||||||
|
/// </summary> |
||||||
|
public MultiTenancySides MultiTenancySide { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 子菜单 |
||||||
|
/// </summary> |
||||||
|
public List<MenuDto> Children { get; set; } = new List<MenuDto>(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
using Volo.Abp.Application; |
||||||
|
using Volo.Abp.Authorization; |
||||||
|
using Volo.Abp.Modularity; |
||||||
|
using Volo.Abp.PermissionManagement; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
[DependsOn( |
||||||
|
typeof(AbpPermissionManagementApplicationContractsModule), |
||||||
|
typeof(MenuManagementDomainSharedModule), |
||||||
|
typeof(AbpDddApplicationContractsModule), |
||||||
|
typeof(AbpAuthorizationModule) |
||||||
|
)] |
||||||
|
public class MenuManagementApplicationContractsModule : AbpModule |
||||||
|
{ |
||||||
|
|
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
public class MenuManagementRemoteServiceConsts |
||||||
|
{ |
||||||
|
public const string RemoteServiceName = "MenuManagement"; |
||||||
|
|
||||||
|
public const string ModuleName = "menuManagement"; |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuMeta |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 标题 |
||||||
|
/// </summary> |
||||||
|
public string Title { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 图标 |
||||||
|
/// </summary> |
||||||
|
public string Icon { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuRequestDto |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 名称 |
||||||
|
/// </summary> |
||||||
|
public string Name { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 类型 |
||||||
|
/// </summary> |
||||||
|
public MenuEnumType? Type { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
using Sanhe.Abp.MenuManagement.Localization; |
||||||
|
using Volo.Abp.Authorization.Permissions; |
||||||
|
using Volo.Abp.Localization; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.Permissions; |
||||||
|
|
||||||
|
public class MenuManagementPermissionDefinitionProvider : PermissionDefinitionProvider |
||||||
|
{ |
||||||
|
public override void Define(IPermissionDefinitionContext context) |
||||||
|
{ |
||||||
|
var moduleGroup = context.AddGroup(MenuManagementPermissions.GroupName, L("MenuManagement:MenuManagement")); |
||||||
|
var permission = moduleGroup.AddPermission(MenuManagementPermissions.Menus.Default, L("MenuManagement:MenuManagement"), multiTenancySide: MultiTenancySides.Host); |
||||||
|
permission.AddChild(MenuManagementPermissions.Menus.Create, L("MenuManagement:Create"), multiTenancySide: MultiTenancySides.Host); |
||||||
|
permission.AddChild(MenuManagementPermissions.Menus.Update, L("MenuManagement:Update"), multiTenancySide: MultiTenancySides.Host); |
||||||
|
permission.AddChild(MenuManagementPermissions.Menus.Delete, L("MenuManagement:Delete"), multiTenancySide: MultiTenancySides.Host); |
||||||
|
permission.AddChild(MenuManagementPermissions.Menus.CreatePermission, L("MenuManagement:CreatePermission"), multiTenancySide: MultiTenancySides.Host); |
||||||
|
} |
||||||
|
|
||||||
|
private static LocalizableString L(string name) |
||||||
|
{ |
||||||
|
return LocalizableString.Create<MenuManagementResource>(name); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
using Volo.Abp.Reflection; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.Permissions; |
||||||
|
|
||||||
|
public class MenuManagementPermissions |
||||||
|
{ |
||||||
|
public const string GroupName = "MenuManagement"; |
||||||
|
|
||||||
|
public static class Menus |
||||||
|
{ |
||||||
|
public const string Default = GroupName + ".Menus"; |
||||||
|
public const string Create = Default + ".Create"; |
||||||
|
public const string Update = Default + ".Update"; |
||||||
|
public const string Delete = Default + ".Delete"; |
||||||
|
public const string CreatePermission = Default + ".CreatePermission"; |
||||||
|
} |
||||||
|
|
||||||
|
public static string[] GetAll() |
||||||
|
{ |
||||||
|
return ReflectionHelper.GetPublicConstantsRecursively(typeof(MenuManagementPermissions)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
using System; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class UpdateMenuGrantDto |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 菜单Id |
||||||
|
/// </summary> |
||||||
|
public Guid Id { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 权限key |
||||||
|
/// </summary> |
||||||
|
public string PermissionKey { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 是否分配 |
||||||
|
/// </summary> |
||||||
|
public bool IsGranted { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class UpdateMenuGrantsDto |
||||||
|
{ |
||||||
|
public UpdateMenuGrantDto[] Menus { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||||
|
</Weavers> |
@ -0,0 +1,22 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||||
|
<Import Project="..\..\..\common.props" /> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||||
|
<RootNamespace /> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.Application" Version="$(VoloAbpVersion)" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<ProjectReference Include="..\Sanhe.Abp.MenuManagement.Application.Contracts\Sanhe.Abp.MenuManagement.Application.Contracts.csproj" /> |
||||||
|
<ProjectReference Include="..\Sanhe.Abp.MenuManagement.Domain\Sanhe.Abp.MenuManagement.Domain.csproj" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
</Project> |
@ -0,0 +1,182 @@ |
|||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,215 @@ |
|||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
using Sanhe.Abp.MenuManagement.Localization; |
||||||
|
using Volo.Abp.Application.Services; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
public abstract class MenuManagementAppService : ApplicationService |
||||||
|
{ |
||||||
|
protected MenuManagementAppService() |
||||||
|
{ |
||||||
|
LocalizationResource = typeof(MenuManagementResource); |
||||||
|
ObjectMapperContext = typeof(MenuManagementApplicationModule); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
using AutoMapper; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
public class MenuManagementApplicationAutoMapperProfile : Profile |
||||||
|
{ |
||||||
|
public MenuManagementApplicationAutoMapperProfile() |
||||||
|
{ |
||||||
|
CreateMap<Menu, MenuDto>(); |
||||||
|
CreateMap<CreateOrUpdateMenuDto, Menu>(); |
||||||
|
CreateMap<Menu, FrontMenu>() |
||||||
|
.ForMember(d => d.Component, opt => { opt.MapFrom(s => s.ComponentPath); }) |
||||||
|
.ForMember(d => d.Path, opt => { opt.MapFrom(s => s.RouterPath); }) |
||||||
|
.ForMember(d => d.Meta, |
||||||
|
opt => |
||||||
|
{ |
||||||
|
opt.MapFrom(s => new MenuMeta |
||||||
|
{ |
||||||
|
Icon = s.Icon, |
||||||
|
Title = s.DisplayName |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
using Microsoft.Extensions.DependencyInjection; |
||||||
|
using Volo.Abp.Application; |
||||||
|
using Volo.Abp.AutoMapper; |
||||||
|
using Volo.Abp.Modularity; |
||||||
|
using Volo.Abp.PermissionManagement; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
[DependsOn( |
||||||
|
typeof(AbpPermissionManagementApplicationModule), |
||||||
|
typeof(MenuManagementDomainModule), |
||||||
|
typeof(MenuManagementApplicationContractsModule), |
||||||
|
typeof(AbpDddApplicationModule), |
||||||
|
typeof(AbpAutoMapperModule) |
||||||
|
)] |
||||||
|
public class MenuManagementApplicationModule : AbpModule |
||||||
|
{ |
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||||
|
{ |
||||||
|
context.Services.AddAutoMapperObjectMapper<MenuManagementApplicationModule>(); |
||||||
|
Configure<AbpAutoMapperOptions>(options => |
||||||
|
{ |
||||||
|
options.AddMaps<MenuManagementApplicationModule>(); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||||
|
<ConfigureAwait /> |
||||||
|
</Weavers> |
@ -0,0 +1,19 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||||
|
<Import Project="..\..\..\common.props" /> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||||
|
<RootNamespace /> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<PackageReference Include="Volo.Abp.Identity.Domain" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.Identity.Domain.Shared" Version="$(VoloAbpVersion)" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<ProjectReference Include="..\Sanhe.Abp.MenuManagement.Domain\Sanhe.Abp.MenuManagement.Domain.csproj" /> |
||||||
|
</ItemGroup> |
||||||
|
</Project> |
@ -0,0 +1,60 @@ |
|||||||
|
using System; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Authorization.Permissions; |
||||||
|
using Volo.Abp.Guids; |
||||||
|
using Volo.Abp.Identity; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.Identity |
||||||
|
{ |
||||||
|
public class RoleMenuManagementProvider : MenuManagementProvider |
||||||
|
{ |
||||||
|
private readonly IUserRoleFinder _userRoleFinder; |
||||||
|
|
||||||
|
public RoleMenuManagementProvider( |
||||||
|
IMenuGrantRepository menuGrantRepository, |
||||||
|
IPermissionDefinitionManager permissionDefinitionManager, |
||||||
|
IMenuGrantChecker menuGrantChecker, |
||||||
|
IGuidGenerator guidGenerator, |
||||||
|
ICurrentTenant currentTenant, |
||||||
|
IUserRoleFinder userRoleFinder) : |
||||||
|
base(menuGrantRepository, |
||||||
|
permissionDefinitionManager, |
||||||
|
menuGrantChecker, |
||||||
|
guidGenerator, |
||||||
|
currentTenant) |
||||||
|
{ |
||||||
|
_userRoleFinder = userRoleFinder; |
||||||
|
} |
||||||
|
|
||||||
|
public override string Name => RolePermissionValueProvider.ProviderName; |
||||||
|
|
||||||
|
public override async Task<MenuGrantInfo> CheckAsync(Guid menuId, string providerName, string providerKey) |
||||||
|
{ |
||||||
|
if (providerName == Name) |
||||||
|
{ |
||||||
|
return new MenuGrantInfo( |
||||||
|
(await MenuGrantChecker.CheckAsync(menuId, providerName, providerKey)).IsGranted, |
||||||
|
providerKey |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
if (providerName == UserPermissionValueProvider.ProviderName) |
||||||
|
{ |
||||||
|
var userId = Guid.Parse(providerKey); |
||||||
|
var roleNames = await _userRoleFinder.GetRolesAsync(userId); |
||||||
|
|
||||||
|
foreach (var roleName in roleNames) |
||||||
|
{ |
||||||
|
var grantCache = await MenuGrantChecker.CheckAsync(menuId, Name, roleName); |
||||||
|
if (grantCache.IsGranted) |
||||||
|
{ |
||||||
|
return new MenuGrantInfo(true, roleName); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return MenuGrantInfo.NonGranted; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
using Volo.Abp.Authorization.Permissions; |
||||||
|
using Volo.Abp.Guids; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.Identity |
||||||
|
{ |
||||||
|
public class UserMenuManagementProvider : MenuManagementProvider |
||||||
|
{ |
||||||
|
public UserMenuManagementProvider( |
||||||
|
IMenuGrantRepository menuGrantRepository, |
||||||
|
IPermissionDefinitionManager permissionDefinitionManager, |
||||||
|
IMenuGrantChecker menuGrantChecker, |
||||||
|
IGuidGenerator guidGenerator, |
||||||
|
ICurrentTenant currentTenant) : |
||||||
|
base(menuGrantRepository, permissionDefinitionManager, menuGrantChecker, guidGenerator, currentTenant) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public override string Name => UserPermissionValueProvider.ProviderName; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
using Sanhe.Abp.MenuManagement.Identity; |
||||||
|
using Volo.Abp.Identity; |
||||||
|
using Volo.Abp.Modularity; |
||||||
|
using Volo.Abp.PermissionManagement; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
[DependsOn( |
||||||
|
typeof(AbpIdentityDomainSharedModule), |
||||||
|
typeof(AbpPermissionManagementDomainModule), |
||||||
|
typeof(MenuManagementDomainModule) |
||||||
|
)] |
||||||
|
public class MenuManagementDomainIdentityModule : AbpModule |
||||||
|
{ |
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||||
|
{ |
||||||
|
Configure<MenuManagementOptions>(options => |
||||||
|
{ |
||||||
|
options.ManagementProviders.Add<UserMenuManagementProvider>(); |
||||||
|
options.ManagementProviders.Add<RoleMenuManagementProvider>(); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||||
|
</Weavers> |
@ -0,0 +1,25 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||||
|
<Import Project="..\..\..\common.props" /> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||||
|
<RootNamespace /> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<None Remove="Sanhe\Abp\MenuManagement\Localization\Resources\en.json" /> |
||||||
|
<None Remove="Sanhe\Abp\MenuManagement\Localization\Resources\zh-Hans.json" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<EmbeddedResource Include="Sanhe\Abp\MenuManagement\Localization\Resources\en.json" /> |
||||||
|
<EmbeddedResource Include="Sanhe\Abp\MenuManagement\Localization\Resources\zh-Hans.json" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Shared" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.Validation" Version="$(VoloAbpVersion)" /> |
||||||
|
</ItemGroup> |
||||||
|
</Project> |
@ -0,0 +1,9 @@ |
|||||||
|
using Volo.Abp.Localization; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.Localization; |
||||||
|
|
||||||
|
[LocalizationResourceName("MenuManagement")] |
||||||
|
public class MenuManagementResource |
||||||
|
{ |
||||||
|
|
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
{ |
||||||
|
"culture": "en", |
||||||
|
"texts": { |
||||||
|
"ManageYourProfile": "Manage your profile", |
||||||
|
"Menu:Menu": "MenuMenu", |
||||||
|
"Menu": "Menu", |
||||||
|
"MenuTenantId": "MenuTenantId", |
||||||
|
"MenuName": "MenuName", |
||||||
|
"MenuDisplayName": "MenuDisplayName", |
||||||
|
"MenuMenuType": "MenuMenuType", |
||||||
|
"MenuComponentPath": "MenuComponentPath", |
||||||
|
"MenuRouterPath": "MenuRouterPath", |
||||||
|
"MenuParentId": "MenuParentId", |
||||||
|
"MenuParent": "MenuParent", |
||||||
|
"MenuIcon": "MenuIcon", |
||||||
|
"MenuSort": "MenuSort", |
||||||
|
"MenuTargetUrl": "MenuTargetUrl", |
||||||
|
"MenuPermissionKey": "MenuPermissionKey", |
||||||
|
"MenuChildren": "MenuChildren", |
||||||
|
"CreateMenu": "CreateMenu", |
||||||
|
"EditMenu": "EditMenu", |
||||||
|
"MenuDeletionConfirmationMessage": "Are you sure to delete the menu {0}?", |
||||||
|
"SuccessfullyDeleted": "Successfully deleted" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
{ |
||||||
|
"culture": "zh-Hans", |
||||||
|
"texts": { |
||||||
|
"ManageYourProfile": "管理个人资料", |
||||||
|
"Menu:Menu": "MenuMenu", |
||||||
|
"Menu": "Menu", |
||||||
|
"MenuTenantId": "MenuTenantId", |
||||||
|
"MenuName": "MenuName", |
||||||
|
"MenuDisplayName": "MenuDisplayName", |
||||||
|
"MenuMenuType": "MenuMenuType", |
||||||
|
"MenuComponentPath": "MenuComponentPath", |
||||||
|
"MenuRouterPath": "MenuRouterPath", |
||||||
|
"MenuParentId": "MenuParentId", |
||||||
|
"MenuParent": "MenuParent", |
||||||
|
"MenuIcon": "MenuIcon", |
||||||
|
"MenuSort": "MenuSort", |
||||||
|
"MenuTargetUrl": "MenuTargetUrl", |
||||||
|
"MenuPermissionKey": "MenuPermissionKey", |
||||||
|
"MenuChildren": "MenuChildren", |
||||||
|
"CreateMenu": "CreateMenu", |
||||||
|
"EditMenu": "EditMenu", |
||||||
|
"MenuDeletionConfirmationMessage": "Are you sure to delete the menu {0}?", |
||||||
|
"SuccessfullyDeleted": "Successfully deleted", |
||||||
|
"MenuManagement:MenuManagement": "菜单管理", |
||||||
|
"MenuManagement:Create": "创建", |
||||||
|
"MenuManagement:Update": "编辑", |
||||||
|
"MenuManagement:Delete": "删除", |
||||||
|
"MenuManagement:CreatePermission": "创建权限" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 菜单类型 |
||||||
|
/// </summary> |
||||||
|
public enum MenuEnumType |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 菜单 |
||||||
|
/// </summary> |
||||||
|
Menu, |
||||||
|
/// <summary> |
||||||
|
/// 权限 |
||||||
|
/// </summary> |
||||||
|
Permission |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public static class MenuGrantConsts |
||||||
|
{ |
||||||
|
public const int MaxProviderNameLength = 64; |
||||||
|
|
||||||
|
public const int MaxProviderKeyLength = 64; |
||||||
|
} |
||||||
|
|
||||||
|
public static class MenuConsts |
||||||
|
{ |
||||||
|
public const int MaxProviderNameLength = 64; |
||||||
|
|
||||||
|
public const int MaxProviderKeyLength = 64; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuGrantInfoDto |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Id |
||||||
|
/// </summary> |
||||||
|
public Guid Id { get; set; } |
||||||
|
public string Name { get; set; } |
||||||
|
public string DisplayName { get; set; } |
||||||
|
public string PermissionKey { get; set; } |
||||||
|
public bool IsGranted { get; set; } |
||||||
|
public List<MenuProviderInfo> GrantedProviders { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
using Sanhe.Abp.MenuManagement.Localization; |
||||||
|
using Volo.Abp.Localization; |
||||||
|
using Volo.Abp.Localization.ExceptionHandling; |
||||||
|
using Volo.Abp.Modularity; |
||||||
|
using Volo.Abp.PermissionManagement; |
||||||
|
using Volo.Abp.Validation; |
||||||
|
using Volo.Abp.Validation.Localization; |
||||||
|
using Volo.Abp.VirtualFileSystem; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
[DependsOn( |
||||||
|
typeof(AbpValidationModule), |
||||||
|
typeof(AbpPermissionManagementDomainSharedModule) |
||||||
|
)] |
||||||
|
public class MenuManagementDomainSharedModule : AbpModule |
||||||
|
{ |
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||||
|
{ |
||||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||||
|
{ |
||||||
|
options.FileSets.AddEmbedded<MenuManagementDomainSharedModule>(); |
||||||
|
}); |
||||||
|
|
||||||
|
Configure<AbpLocalizationOptions>(options => |
||||||
|
{ |
||||||
|
options.Resources |
||||||
|
.Add<MenuManagementResource>("en") |
||||||
|
.AddBaseTypes(typeof(AbpValidationResource)) |
||||||
|
.AddVirtualJson("/Sanhe/Abp/MenuManagement/Localization/Resources"); |
||||||
|
}); |
||||||
|
|
||||||
|
Configure<AbpExceptionLocalizationOptions>(options => |
||||||
|
{ |
||||||
|
options.MapCodeNamespace("MenuManagement", typeof(MenuManagementResource)); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
using JetBrains.Annotations; |
||||||
|
using Volo.Abp; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuProviderInfo |
||||||
|
{ |
||||||
|
public string Name { get; } |
||||||
|
|
||||||
|
public string Key { get; } |
||||||
|
|
||||||
|
public MenuProviderInfo([NotNull] string name, [NotNull] string key) |
||||||
|
{ |
||||||
|
Check.NotNull(name, nameof(name)); |
||||||
|
Check.NotNull(key, nameof(key)); |
||||||
|
|
||||||
|
Name = name; |
||||||
|
Key = key; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||||
|
</Weavers> |
@ -0,0 +1,20 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||||
|
<Import Project="..\..\..\common.props" /> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||||
|
<RootNamespace /> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.Domain" Version="$(VoloAbpVersion)" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<ProjectReference Include="..\Sanhe.Abp.MenuManagement.Domain.Shared\Sanhe.Abp.MenuManagement.Domain.Shared.csproj" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
</Project> |
@ -0,0 +1,10 @@ |
|||||||
|
using System; |
||||||
|
using System.Threading.Tasks; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IMenuGrantChecker |
||||||
|
{ |
||||||
|
Task<MenuGrantCacheItem> CheckAsync(Guid menuId, string providerName, string providerKey); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Threading; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Domain.Repositories; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IMenuGrantRepository : IBasicRepository<MenuGrant, Guid> |
||||||
|
{ |
||||||
|
Task<MenuGrant> FindAsync(Guid menuId, |
||||||
|
string providerName, |
||||||
|
string providerKey, |
||||||
|
CancellationToken cancellationToken = default); |
||||||
|
|
||||||
|
Task<List<MenuGrant>> GetListAsync( |
||||||
|
string providerName, |
||||||
|
string providerKey, |
||||||
|
CancellationToken cancellationToken = default |
||||||
|
); |
||||||
|
|
||||||
|
Task<List<MenuGrant>> GetGrantByMenuIdAsync(Guid menuId, bool noTracking = true); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
using System.Threading.Tasks; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IMenuGrantRuntimeCheckerProvider |
||||||
|
{ |
||||||
|
Task<MenuGrantResultEnum> CheckAsync(MenuGrantRuntimeCheckerContent context); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
using JetBrains.Annotations; |
||||||
|
using System; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.DependencyInjection; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IMenuManagementProvider : ITransientDependency |
||||||
|
{ |
||||||
|
string Name { get; } |
||||||
|
|
||||||
|
Task<MenuGrantInfo> CheckAsync( |
||||||
|
[NotNull] Guid menuId, |
||||||
|
[NotNull] string providerName, |
||||||
|
[NotNull] string providerKey |
||||||
|
); |
||||||
|
|
||||||
|
Task SetAsync( |
||||||
|
[NotNull] Guid menuId, |
||||||
|
[NotNull] string providerKey, |
||||||
|
bool isGranted |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Authorization.Permissions; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IMenuManager |
||||||
|
{ |
||||||
|
IReadOnlyList<PermissionDefinition> GetPermissions(string providerName); |
||||||
|
Task<MenuWithGrantedProviders> GetAsync(Guid menuId, string providerName, string providerKey); |
||||||
|
Task SetAsync(Guid menuId, string providerName, string providerKey, bool isGranted); |
||||||
|
Task UpdatePermissionGrantAsync(Guid menuId, string oldPermission, string newPermission); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
using System; |
||||||
|
using Volo.Abp.Domain.Repositories; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IMenuRepository : IRepository<Menu, Guid> |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Security.Claims; |
||||||
|
using System.Security.Principal; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.DependencyInjection; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public interface IUserMenuGrantChecker |
||||||
|
{ |
||||||
|
Task<bool> CheckAsync(ClaimsPrincipal claimsPrincipal, Menu menu); |
||||||
|
} |
||||||
|
|
||||||
|
public class UserMenuGrantChecker : IUserMenuGrantChecker, ITransientDependency |
||||||
|
{ |
||||||
|
private readonly ICurrentTenant _currentTenant; |
||||||
|
private readonly IEnumerable<IMenuGrantRuntimeCheckerProvider> _checkerProviders; |
||||||
|
|
||||||
|
public UserMenuGrantChecker( |
||||||
|
ICurrentTenant currentTenant, |
||||||
|
IEnumerable<IMenuGrantRuntimeCheckerProvider> checkerProviders |
||||||
|
) |
||||||
|
{ |
||||||
|
_currentTenant = currentTenant; |
||||||
|
_checkerProviders = checkerProviders; |
||||||
|
} |
||||||
|
|
||||||
|
public async Task<bool> CheckAsync(ClaimsPrincipal claimsPrincipal, Menu menu) |
||||||
|
{ |
||||||
|
var multiTenancySide = claimsPrincipal?.GetMultiTenancySide() |
||||||
|
?? _currentTenant.GetMultiTenancySide(); |
||||||
|
|
||||||
|
if (!menu.MultiTenancySide.HasFlag(multiTenancySide)) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (menu.PermissionKey.IsNullOrWhiteSpace()) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
var isGranted = false; |
||||||
|
var content = new MenuGrantRuntimeCheckerContent |
||||||
|
{ |
||||||
|
Menu = menu, |
||||||
|
Principal = claimsPrincipal |
||||||
|
}; |
||||||
|
|
||||||
|
foreach (var provider in _checkerProviders) |
||||||
|
{ |
||||||
|
var result = await provider.CheckAsync(content); |
||||||
|
if (result == MenuGrantResultEnum.Granted) |
||||||
|
{ |
||||||
|
isGranted = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return isGranted; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,100 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.ObjectModel; |
||||||
|
using System.ComponentModel; |
||||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 菜单 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("菜单")] |
||||||
|
public class Menu : FullAuditedAggregateRoot<Guid> |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 名称 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("名称")] |
||||||
|
public virtual string Name { get; protected set; } |
||||||
|
/// <summary> |
||||||
|
/// 显示名称 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("显示名称")] |
||||||
|
public virtual string DisplayName { get; protected set; } |
||||||
|
/// <summary> |
||||||
|
/// 类型 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("类型")] |
||||||
|
public virtual MenuEnumType MenuType { get; protected set; } |
||||||
|
/// <summary> |
||||||
|
/// 组件路径 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("组件路径")] |
||||||
|
public virtual string ComponentPath { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 路由路径 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("路由路径")] |
||||||
|
public virtual string RouterPath { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 父Id |
||||||
|
/// </summary> |
||||||
|
[DisplayName("父Id")] |
||||||
|
public virtual Guid? ParentId { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 图标 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("图标")] |
||||||
|
public virtual string Icon { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 排序 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("排序")] |
||||||
|
public virtual string Sort { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// window.open _blank |
||||||
|
/// </summary> |
||||||
|
[DisplayName("window.open _blank ")] |
||||||
|
public virtual string TargetUrl { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 此菜单关联的权限key |
||||||
|
/// </summary> |
||||||
|
[DisplayName("此菜单关联的权限key")] |
||||||
|
public virtual string PermissionKey { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 表示多租户应用程序中的所属方 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("表示多租户应用程序中的所属方")] |
||||||
|
public virtual MultiTenancySides MultiTenancySide { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 父菜单 |
||||||
|
/// </summary> |
||||||
|
public virtual Menu Parent { get; set; } |
||||||
|
/// <summary> |
||||||
|
/// 子菜单 |
||||||
|
/// </summary> |
||||||
|
public virtual Collection<Menu> Children { get; set; } |
||||||
|
|
||||||
|
protected Menu() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public Menu( |
||||||
|
Guid id, |
||||||
|
string name, |
||||||
|
string displayName, |
||||||
|
MenuEnumType menuType, |
||||||
|
MultiTenancySides multiTenancySide = MultiTenancySides.Both |
||||||
|
) |
||||||
|
{ |
||||||
|
Id = id; |
||||||
|
Name = name; |
||||||
|
DisplayName = displayName; |
||||||
|
MenuType = menuType; |
||||||
|
MultiTenancySide = multiTenancySide; |
||||||
|
|
||||||
|
Children = new Collection<Menu>(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
using JetBrains.Annotations; |
||||||
|
using System; |
||||||
|
using System.ComponentModel; |
||||||
|
using Volo.Abp; |
||||||
|
using Volo.Abp.Domain.Entities; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 菜单分配 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("菜单分配")] |
||||||
|
public class MenuGrant : Entity<Guid>, IMultiTenant |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 租户Id |
||||||
|
/// </summary> |
||||||
|
[DisplayName("租户Id")] |
||||||
|
public virtual Guid? TenantId { get; protected set; } |
||||||
|
/// <summary> |
||||||
|
/// 菜单Id |
||||||
|
/// </summary> |
||||||
|
[DisplayName("菜单Id")] |
||||||
|
[NotNull] |
||||||
|
public virtual Guid MenuId { get; protected set; } |
||||||
|
/// <summary> |
||||||
|
/// 提供器名称 |
||||||
|
/// </summary> |
||||||
|
[DisplayName("提供器名称")] |
||||||
|
[NotNull] |
||||||
|
public virtual string ProviderName { get; protected set; } |
||||||
|
/// <summary> |
||||||
|
/// 提供器Key |
||||||
|
/// </summary> |
||||||
|
[DisplayName("提供器Key")] |
||||||
|
[CanBeNull] |
||||||
|
public virtual string ProviderKey { get; protected internal set; } |
||||||
|
|
||||||
|
protected MenuGrant() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public MenuGrant( |
||||||
|
Guid id, |
||||||
|
[NotNull] Guid menuId, |
||||||
|
[NotNull] string providerName, |
||||||
|
[CanBeNull] string providerKey, |
||||||
|
Guid? tenantId = null) |
||||||
|
{ |
||||||
|
Check.NotNull(menuId, nameof(menuId)); |
||||||
|
|
||||||
|
Id = id; |
||||||
|
MenuId = menuId; |
||||||
|
ProviderName = Check.NotNullOrWhiteSpace(providerName, nameof(providerName)); |
||||||
|
ProviderKey = providerKey; |
||||||
|
TenantId = tenantId; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
using System; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
[Serializable] |
||||||
|
public class MenuGrantCacheItem |
||||||
|
{ |
||||||
|
public Guid MenuId { get; set; } |
||||||
|
public bool IsGranted { get; set; } |
||||||
|
|
||||||
|
public MenuGrantCacheItem() |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public MenuGrantCacheItem(Guid menuId, bool isGranted) |
||||||
|
{ |
||||||
|
MenuId = menuId; |
||||||
|
IsGranted = isGranted; |
||||||
|
} |
||||||
|
|
||||||
|
public static string CalculateCacheKey(Guid menuId, string providerName, string providerKey) |
||||||
|
{ |
||||||
|
return "pn:" + providerName + ",pk:" + providerKey + ",m:" + menuId; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
using System; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Caching; |
||||||
|
using Volo.Abp.DependencyInjection; |
||||||
|
using Volo.Abp.Domain.Entities.Events; |
||||||
|
using Volo.Abp.EventBus; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuGrantCacheItemInvalidator : |
||||||
|
ILocalEventHandler<EntityCreatedEventData<MenuGrant>>, |
||||||
|
ILocalEventHandler<EntityDeletedEventData<MenuGrant>>, |
||||||
|
ITransientDependency |
||||||
|
{ |
||||||
|
public MenuGrantCacheItemInvalidator( |
||||||
|
ICurrentTenant currentTenant, |
||||||
|
IDistributedCache<MenuGrantCacheItem> cache |
||||||
|
) |
||||||
|
{ |
||||||
|
CurrentTenant = currentTenant; |
||||||
|
Cache = cache; |
||||||
|
} |
||||||
|
|
||||||
|
protected ICurrentTenant CurrentTenant { get; } |
||||||
|
|
||||||
|
protected IDistributedCache<MenuGrantCacheItem> Cache { get; } |
||||||
|
|
||||||
|
public async Task HandleEventAsync(EntityCreatedEventData<MenuGrant> eventData) |
||||||
|
{ |
||||||
|
var cacheKey = CalculateCacheKey( |
||||||
|
eventData.Entity.MenuId, |
||||||
|
eventData.Entity.ProviderName, |
||||||
|
eventData.Entity.ProviderKey |
||||||
|
); |
||||||
|
|
||||||
|
using (CurrentTenant.Change(eventData.Entity.TenantId)) |
||||||
|
{ |
||||||
|
await Cache.SetAsync(cacheKey, new MenuGrantCacheItem(eventData.Entity.MenuId, true)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public async Task HandleEventAsync(EntityDeletedEventData<MenuGrant> eventData) |
||||||
|
{ |
||||||
|
var cacheKey = CalculateCacheKey( |
||||||
|
eventData.Entity.MenuId, |
||||||
|
eventData.Entity.ProviderName, |
||||||
|
eventData.Entity.ProviderKey |
||||||
|
); |
||||||
|
|
||||||
|
using (CurrentTenant.Change(eventData.Entity.TenantId)) |
||||||
|
{ |
||||||
|
await Cache.SetAsync(cacheKey, new MenuGrantCacheItem(eventData.Entity.MenuId, false)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected virtual string CalculateCacheKey( |
||||||
|
Guid menuId, |
||||||
|
string providerName, |
||||||
|
string providerKey) |
||||||
|
{ |
||||||
|
return MenuGrantCacheItem.CalculateCacheKey(menuId, providerName, providerKey); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
using Microsoft.Extensions.Logging; |
||||||
|
using System; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Caching; |
||||||
|
using Volo.Abp.DependencyInjection; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuGrantChecker : IMenuGrantChecker, ITransientDependency |
||||||
|
{ |
||||||
|
private readonly IDistributedCache<MenuGrantCacheItem> _cache; |
||||||
|
private readonly ILogger<MenuGrantChecker> _logger; |
||||||
|
private readonly IMenuGrantRepository _menuGrantRepository; |
||||||
|
|
||||||
|
public MenuGrantChecker( |
||||||
|
IDistributedCache<MenuGrantCacheItem> cache, |
||||||
|
ILogger<MenuGrantChecker> logger, |
||||||
|
IMenuGrantRepository menuGrantRepository |
||||||
|
) |
||||||
|
{ |
||||||
|
_cache = cache; |
||||||
|
_logger = logger; |
||||||
|
_menuGrantRepository = menuGrantRepository; |
||||||
|
} |
||||||
|
|
||||||
|
public async Task<MenuGrantCacheItem> CheckAsync(Guid menuId, string providerName, string providerKey) |
||||||
|
{ |
||||||
|
var cacheKey = MenuGrantCacheItem.CalculateCacheKey(menuId, providerName, providerKey); |
||||||
|
|
||||||
|
_logger.LogDebug("MenuGrantCheckerCache.CheckAsync: {cacheKey}", cacheKey); |
||||||
|
|
||||||
|
var cacheItem = await _cache.GetAsync(cacheKey); |
||||||
|
|
||||||
|
if (cacheItem != null) |
||||||
|
{ |
||||||
|
_logger.LogDebug("Found in the cache: {cacheKey}", cacheKey); |
||||||
|
return cacheItem; |
||||||
|
} |
||||||
|
|
||||||
|
_logger.LogDebug("Not found in the cache, getting from the repository: {cacheKey}", cacheKey); |
||||||
|
|
||||||
|
cacheItem = new MenuGrantCacheItem( |
||||||
|
menuId, |
||||||
|
await _menuGrantRepository.FindAsync(menuId, providerName, providerKey) != null |
||||||
|
); |
||||||
|
|
||||||
|
_logger.LogDebug("Setting the cache item: {cacheKey}", cacheKey); |
||||||
|
|
||||||
|
await _cache.SetAsync( |
||||||
|
cacheKey, |
||||||
|
cacheItem |
||||||
|
); |
||||||
|
|
||||||
|
_logger.LogDebug("Finished setting the cache item: {cacheKey}", cacheKey); |
||||||
|
|
||||||
|
return cacheItem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
using JetBrains.Annotations; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuGrantInfo |
||||||
|
{ |
||||||
|
public static MenuGrantInfo NonGranted { get; } = new MenuGrantInfo(false); |
||||||
|
|
||||||
|
public virtual bool IsGranted { get; } |
||||||
|
|
||||||
|
public virtual string ProviderKey { get; } |
||||||
|
|
||||||
|
public MenuGrantInfo(bool isGranted, [CanBeNull] string providerKey = null) |
||||||
|
{ |
||||||
|
IsGranted = isGranted; |
||||||
|
ProviderKey = providerKey; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public enum MenuGrantResultEnum |
||||||
|
{ |
||||||
|
Undefined, |
||||||
|
Granted |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
using System.Security.Claims; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuGrantRuntimeCheckerContent |
||||||
|
{ |
||||||
|
public Menu Menu { get; set; } |
||||||
|
public ClaimsPrincipal Principal { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
using System.Linq; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.DependencyInjection; |
||||||
|
using Volo.Abp.Security.Claims; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public abstract class MenuGrantRuntimeCheckerProvider : IMenuGrantRuntimeCheckerProvider |
||||||
|
{ |
||||||
|
protected IMenuGrantChecker MenuGrantChecker { get; } |
||||||
|
|
||||||
|
protected MenuGrantRuntimeCheckerProvider(IMenuGrantChecker menuGrantChecker) |
||||||
|
{ |
||||||
|
MenuGrantChecker = menuGrantChecker; |
||||||
|
} |
||||||
|
|
||||||
|
public abstract Task<MenuGrantResultEnum> CheckAsync(MenuGrantRuntimeCheckerContent context); |
||||||
|
} |
||||||
|
|
||||||
|
public class RoleMenuGrantRuntimeCheckerProvider : MenuGrantRuntimeCheckerProvider, ITransientDependency |
||||||
|
{ |
||||||
|
public RoleMenuGrantRuntimeCheckerProvider(IMenuGrantChecker menuGrantChecker) : base(menuGrantChecker) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public override async Task<MenuGrantResultEnum> CheckAsync(MenuGrantRuntimeCheckerContent context) |
||||||
|
{ |
||||||
|
var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray(); |
||||||
|
|
||||||
|
if (roles == null || !roles.Any()) |
||||||
|
{ |
||||||
|
return MenuGrantResultEnum.Undefined; |
||||||
|
} |
||||||
|
|
||||||
|
foreach (var role in roles) |
||||||
|
{ |
||||||
|
var result = await MenuGrantChecker.CheckAsync(context.Menu.Id, "R", role); |
||||||
|
if (result.IsGranted) |
||||||
|
{ |
||||||
|
return MenuGrantResultEnum.Granted; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return MenuGrantResultEnum.Undefined; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class UserMenuGrantRuntimeCheckerProvider : MenuGrantRuntimeCheckerProvider, ITransientDependency |
||||||
|
{ |
||||||
|
public UserMenuGrantRuntimeCheckerProvider(IMenuGrantChecker menuGrantChecker) : base(menuGrantChecker) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public override async Task<MenuGrantResultEnum> CheckAsync(MenuGrantRuntimeCheckerContent context) |
||||||
|
{ |
||||||
|
var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value; |
||||||
|
var result = await MenuGrantChecker.CheckAsync(context.Menu.Id, "U", userId); |
||||||
|
return result.IsGranted ? MenuGrantResultEnum.Granted : MenuGrantResultEnum.Undefined; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
public static class MenuManagementDbProperties |
||||||
|
{ |
||||||
|
public static string DbTablePrefix { get; set; } = "MenuManagement"; |
||||||
|
|
||||||
|
public static string DbSchema { get; set; } = null; |
||||||
|
|
||||||
|
public const string ConnectionStringName = "MenuManagement"; |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
using Volo.Abp.Domain; |
||||||
|
using Volo.Abp.Modularity; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
[DependsOn( |
||||||
|
typeof(AbpDddDomainModule), |
||||||
|
typeof(MenuManagementDomainSharedModule) |
||||||
|
)] |
||||||
|
public class MenuManagementDomainModule : AbpModule |
||||||
|
{ |
||||||
|
|
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
using Volo.Abp.Collections; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuManagementOptions |
||||||
|
{ |
||||||
|
public ITypeList<IMenuManagementProvider> ManagementProviders { get; } |
||||||
|
|
||||||
|
public MenuManagementOptions() |
||||||
|
{ |
||||||
|
ManagementProviders = new TypeList<IMenuManagementProvider>(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
using System; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Authorization.Permissions; |
||||||
|
using Volo.Abp.Guids; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public abstract class MenuManagementProvider : IMenuManagementProvider |
||||||
|
{ |
||||||
|
protected IMenuGrantRepository MenuGrantRepository { get; } |
||||||
|
protected IPermissionDefinitionManager PermissionDefinitionManager { get; } |
||||||
|
protected IMenuGrantChecker MenuGrantChecker { get; } |
||||||
|
protected IGuidGenerator GuidGenerator { get; } |
||||||
|
protected ICurrentTenant CurrentTenant { get; } |
||||||
|
public abstract string Name { get; } |
||||||
|
|
||||||
|
protected MenuManagementProvider(IMenuGrantRepository menuGrantRepository, |
||||||
|
IPermissionDefinitionManager permissionDefinitionManager, |
||||||
|
IMenuGrantChecker menuGrantChecker, |
||||||
|
IGuidGenerator guidGenerator, |
||||||
|
ICurrentTenant currentTenant) |
||||||
|
{ |
||||||
|
MenuGrantRepository = menuGrantRepository; |
||||||
|
PermissionDefinitionManager = permissionDefinitionManager; |
||||||
|
MenuGrantChecker = menuGrantChecker; |
||||||
|
GuidGenerator = guidGenerator; |
||||||
|
CurrentTenant = currentTenant; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual async Task<MenuGrantInfo> CheckAsync(Guid menuId, string providerName, string providerKey) |
||||||
|
{ |
||||||
|
if (providerName != Name) |
||||||
|
{ |
||||||
|
return MenuGrantInfo.NonGranted; |
||||||
|
} |
||||||
|
|
||||||
|
return new MenuGrantInfo( |
||||||
|
(await MenuGrantChecker.CheckAsync(menuId, providerName, providerKey)).IsGranted, |
||||||
|
providerKey |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual Task SetAsync(Guid menuId, string providerKey, bool isGranted) |
||||||
|
{ |
||||||
|
return isGranted |
||||||
|
? GrantAsync(menuId, providerKey) |
||||||
|
: RevokeAsync(menuId, providerKey); |
||||||
|
} |
||||||
|
|
||||||
|
protected virtual async Task GrantAsync(Guid menuId, string providerKey) |
||||||
|
{ |
||||||
|
var menuGrant = await MenuGrantRepository.FindAsync(menuId, Name, providerKey); |
||||||
|
if (menuGrant != null) |
||||||
|
{ |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
await MenuGrantRepository.InsertAsync( |
||||||
|
new MenuGrant( |
||||||
|
GuidGenerator.Create(), |
||||||
|
menuId, |
||||||
|
Name, |
||||||
|
providerKey, |
||||||
|
CurrentTenant.Id |
||||||
|
) |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
protected virtual async Task RevokeAsync(Guid menuId, string providerKey) |
||||||
|
{ |
||||||
|
var permissionGrant = await MenuGrantRepository.FindAsync(menuId, Name, providerKey); |
||||||
|
if (permissionGrant == null) |
||||||
|
{ |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
await MenuGrantRepository.DeleteAsync(permissionGrant); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,116 @@ |
|||||||
|
using Microsoft.Extensions.DependencyInjection; |
||||||
|
using Microsoft.Extensions.Options; |
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Collections.Immutable; |
||||||
|
using System.Linq; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp; |
||||||
|
using Volo.Abp.Authorization.Permissions; |
||||||
|
using Volo.Abp.DependencyInjection; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
using Volo.Abp.PermissionManagement; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuManager : IMenuManager, ITransientDependency |
||||||
|
{ |
||||||
|
private readonly IPermissionDefinitionManager _permissionDefinitionManager; |
||||||
|
private readonly IMenuGrantRepository _menuGrantRepository; |
||||||
|
private readonly IPermissionManager _permissionManager; |
||||||
|
private readonly ICurrentTenant _currentTenant; |
||||||
|
private readonly IReadOnlyList<IMenuManagementProvider> _managementProviders; |
||||||
|
private readonly MenuManagementOptions _options; |
||||||
|
|
||||||
|
public MenuManager( |
||||||
|
IPermissionDefinitionManager permissionDefinitionManager, |
||||||
|
IMenuGrantRepository menuGrantRepository, |
||||||
|
IPermissionManager permissionManager, |
||||||
|
IOptions<MenuManagementOptions> options, |
||||||
|
IServiceProvider serviceProvider, |
||||||
|
ICurrentTenant currentTenant) |
||||||
|
{ |
||||||
|
_permissionDefinitionManager = permissionDefinitionManager; |
||||||
|
_menuGrantRepository = menuGrantRepository; |
||||||
|
_permissionManager = permissionManager; |
||||||
|
_currentTenant = currentTenant; |
||||||
|
_options = options.Value; |
||||||
|
|
||||||
|
_managementProviders = _options.ManagementProviders |
||||||
|
.Select(c => serviceProvider.GetRequiredService(c) as IMenuManagementProvider) |
||||||
|
.ToList(); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual IReadOnlyList<PermissionDefinition> GetPermissions(string providerName) |
||||||
|
{ |
||||||
|
var multiTenancySide = _currentTenant.GetMultiTenancySide(); |
||||||
|
|
||||||
|
var permissions = _permissionDefinitionManager.GetPermissions(); |
||||||
|
return permissions.Where(x => |
||||||
|
{ |
||||||
|
if (x.Providers.Any() && !x.Providers.Contains(providerName)) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (!x.MultiTenancySide.HasFlag(multiTenancySide)) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
}).ToImmutableList(); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual async Task<MenuWithGrantedProviders> GetAsync(Guid menuId, string providerName, string providerKey) |
||||||
|
{ |
||||||
|
var result = new MenuWithGrantedProviders(menuId, false); |
||||||
|
|
||||||
|
foreach (var provider in _managementProviders) |
||||||
|
{ |
||||||
|
var providerResult = await provider.CheckAsync(menuId, providerName, providerKey); |
||||||
|
if (providerResult.IsGranted) |
||||||
|
{ |
||||||
|
result.IsGranted = true; |
||||||
|
result.Providers.Add(new MenuProviderInfo(provider.Name, providerResult.ProviderKey)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual async Task SetAsync(Guid menuId, string providerName, string providerKey, bool isGranted) |
||||||
|
{ |
||||||
|
var currentGrantInfo = await GetAsync(menuId, providerName, providerKey); |
||||||
|
if (currentGrantInfo.IsGranted == isGranted) |
||||||
|
{ |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var provider = _managementProviders.FirstOrDefault(m => m.Name == providerName); |
||||||
|
if (provider == null) |
||||||
|
{ |
||||||
|
throw new UserFriendlyException("Unknown menu management provider: " + providerName); |
||||||
|
} |
||||||
|
|
||||||
|
await provider.SetAsync(menuId, providerKey, isGranted); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual async Task UpdatePermissionGrantAsync(Guid menuId, string oldPermission, string newPermission) |
||||||
|
{ |
||||||
|
var menuGrants = await _menuGrantRepository.GetGrantByMenuIdAsync(menuId); |
||||||
|
foreach (var g in menuGrants) |
||||||
|
{ |
||||||
|
if (!oldPermission.IsNullOrEmpty() && !newPermission.IsNullOrEmpty()) // 菜单原本有权限控制,修改为无权限控制:这种情况不清除授权,视为开放权限。 |
||||||
|
{ |
||||||
|
await _permissionManager.SetAsync(oldPermission, g.ProviderName, g.ProviderKey, false); |
||||||
|
} |
||||||
|
|
||||||
|
if (!newPermission.IsNullOrEmpty()) |
||||||
|
{ |
||||||
|
await _permissionManager.SetAsync(newPermission, g.ProviderName, g.ProviderKey, true); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
using JetBrains.Annotations; |
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using Volo.Abp; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuWithGrantedProviders |
||||||
|
{ |
||||||
|
public Guid MenuId { get; } |
||||||
|
|
||||||
|
public bool IsGranted { get; set; } |
||||||
|
|
||||||
|
public List<MenuProviderInfo> Providers { get; set; } |
||||||
|
|
||||||
|
public MenuWithGrantedProviders([NotNull] Guid menuId, bool isGranted) |
||||||
|
{ |
||||||
|
Check.NotNull(menuId, nameof(menuId)); |
||||||
|
|
||||||
|
MenuId = menuId; |
||||||
|
IsGranted = isGranted; |
||||||
|
|
||||||
|
Providers = new List<MenuProviderInfo>(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.ObjectModel; |
||||||
|
using System.Linq; |
||||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class Permission : AuditedEntity<Guid>, IMultiTenant |
||||||
|
{ |
||||||
|
public virtual Guid? TenantId { get; protected set; } |
||||||
|
public virtual string Key { get; protected set; } |
||||||
|
public virtual string Name { get; protected set; } |
||||||
|
public virtual Guid GroupId { get; protected set; } |
||||||
|
public virtual PermissionGroup Group { get; protected set; } |
||||||
|
public virtual Guid? ParentId { get; set; } |
||||||
|
public virtual Permission Parent { get; set; } |
||||||
|
public virtual Collection<Permission> Children { get; set; } |
||||||
|
|
||||||
|
protected Permission() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public Permission(Guid id, string key, string name, Guid groupId) |
||||||
|
{ |
||||||
|
Id = id; |
||||||
|
Key = key; |
||||||
|
Name = name; |
||||||
|
GroupId = groupId; |
||||||
|
Children = new Collection<Permission>(); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual Permission AddChildren(Guid id, string key, string name) |
||||||
|
{ |
||||||
|
if (Children.Any(x => x.Key == key)) |
||||||
|
{ |
||||||
|
throw new Volo.Abp.UserFriendlyException("权限名重复"); |
||||||
|
} |
||||||
|
|
||||||
|
var page = new Permission(id, key, name, GroupId); |
||||||
|
page.Parent = this; |
||||||
|
page.ParentId = Id; |
||||||
|
Children.Add(page); |
||||||
|
|
||||||
|
return page; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.ObjectModel; |
||||||
|
using System.Linq; |
||||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||||
|
using Volo.Abp.MultiTenancy; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class PermissionGroup : AuditedEntity<Guid>, IMultiTenant |
||||||
|
{ |
||||||
|
public virtual Guid? TenantId { get; protected set; } |
||||||
|
public virtual string Key { get; protected set; } |
||||||
|
public virtual string Name { get; protected set; } |
||||||
|
public virtual Guid? ParentId { get; set; } |
||||||
|
public virtual PermissionGroup Parent { get; set; } |
||||||
|
public virtual Collection<PermissionGroup> Children { get; set; } |
||||||
|
public virtual Collection<Permission> Permissions { get; set; } |
||||||
|
|
||||||
|
protected PermissionGroup() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public PermissionGroup(Guid id, string key, string name, Guid? tenantId) |
||||||
|
{ |
||||||
|
Id = id; |
||||||
|
Key = key; |
||||||
|
Name = name; |
||||||
|
TenantId = tenantId; |
||||||
|
|
||||||
|
Children = new Collection<PermissionGroup>(); |
||||||
|
Permissions = new Collection<Permission>(); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual Permission AddPermission(Guid id, string key, string name) |
||||||
|
{ |
||||||
|
if (Permissions.Any(x => x.Key == key)) |
||||||
|
{ |
||||||
|
throw new Volo.Abp.UserFriendlyException("权限名重复"); |
||||||
|
} |
||||||
|
|
||||||
|
var permission = new Permission(id, key, name, Id); |
||||||
|
|
||||||
|
Permissions.Add(permission); |
||||||
|
|
||||||
|
return permission; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual PermissionGroup AddChildren(Guid id, string key, string name, Guid? tenantId = null) |
||||||
|
{ |
||||||
|
if (Children.Any(x => x.Key == key)) |
||||||
|
{ |
||||||
|
throw new Volo.Abp.UserFriendlyException("分组名重复"); |
||||||
|
} |
||||||
|
|
||||||
|
var group = new PermissionGroup(id, key, name, tenantId); |
||||||
|
group.Parent = this; |
||||||
|
group.ParentId = Id; |
||||||
|
Children.Add(group); |
||||||
|
|
||||||
|
return group; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
using Volo.Abp.Settings; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.Settings; |
||||||
|
|
||||||
|
public class MenuManagementSettingDefinitionProvider : SettingDefinitionProvider |
||||||
|
{ |
||||||
|
public override void Define(ISettingDefinitionContext context) |
||||||
|
{ |
||||||
|
/* Define module settings here. |
||||||
|
* Use names from MenuManagementSettings class. |
||||||
|
*/ |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
namespace Sanhe.Abp.MenuManagement.Settings; |
||||||
|
|
||||||
|
public static class MenuManagementSettings |
||||||
|
{ |
||||||
|
public const string GroupName = "MenuManagement"; |
||||||
|
|
||||||
|
/* Add constants for setting names. Example: |
||||||
|
* public const string MySettingName = GroupName + ".MySettingName"; |
||||||
|
*/ |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||||
|
</Weavers> |
@ -0,0 +1,20 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||||
|
<Import Project="..\..\..\common.props" /> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<TargetFramework>net6.0</TargetFramework> |
||||||
|
<RootNamespace /> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="$(VoloAbpVersion)" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<ProjectReference Include="..\Sanhe.Abp.MenuManagement.Domain\Sanhe.Abp.MenuManagement.Domain.csproj" /> |
||||||
|
</ItemGroup> |
||||||
|
|
||||||
|
</Project> |
@ -0,0 +1,12 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
using Volo.Abp.Data; |
||||||
|
using Volo.Abp.EntityFrameworkCore; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.EntityFrameworkCore; |
||||||
|
|
||||||
|
[ConnectionStringName(MenuManagementDbProperties.ConnectionStringName)] |
||||||
|
public interface IMenuManagementDbContext : IEfCoreDbContext |
||||||
|
{ |
||||||
|
DbSet<Menu> Menus { get; set; } |
||||||
|
DbSet<MenuGrant> MenuGrants { get; set; } |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
using Volo.Abp.Data; |
||||||
|
using Volo.Abp.EntityFrameworkCore; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.EntityFrameworkCore; |
||||||
|
|
||||||
|
[ConnectionStringName(MenuManagementDbProperties.ConnectionStringName)] |
||||||
|
public class MenuManagementDbContext : AbpDbContext<MenuManagementDbContext>, IMenuManagementDbContext |
||||||
|
{ |
||||||
|
public DbSet<Menu> Menus { get; set; } |
||||||
|
public DbSet<MenuGrant> MenuGrants { get; set; } |
||||||
|
|
||||||
|
public MenuManagementDbContext(DbContextOptions<MenuManagementDbContext> options) |
||||||
|
: base(options) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder) |
||||||
|
{ |
||||||
|
base.OnModelCreating(builder); |
||||||
|
|
||||||
|
builder.ConfigureMenuManagement(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
using Volo.Abp; |
||||||
|
using Volo.Abp.EntityFrameworkCore.Modeling; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.EntityFrameworkCore; |
||||||
|
|
||||||
|
public static class MenuManagementDbContextModelCreatingExtensions |
||||||
|
{ |
||||||
|
public static void ConfigureMenuManagement( |
||||||
|
this ModelBuilder builder) |
||||||
|
{ |
||||||
|
Check.NotNull(builder, nameof(builder)); |
||||||
|
|
||||||
|
builder.Entity<Menu>(b => |
||||||
|
{ |
||||||
|
b.ToTable(MenuManagementDbProperties.DbTablePrefix + "Menus", MenuManagementDbProperties.DbSchema); |
||||||
|
b.ConfigureByConvention(); |
||||||
|
|
||||||
|
b.Property(x => x.Name).HasMaxLength(50); |
||||||
|
b.Property(x => x.DisplayName).HasMaxLength(50); |
||||||
|
b.Property(x => x.ComponentPath).HasMaxLength(100); |
||||||
|
b.Property(x => x.RouterPath).HasMaxLength(100); |
||||||
|
b.Property(x => x.Icon).HasMaxLength(50); |
||||||
|
b.Property(x => x.Sort).HasMaxLength(50); |
||||||
|
b.Property(x => x.TargetUrl).HasMaxLength(500); |
||||||
|
b.Property(x => x.PermissionKey).HasMaxLength(100); |
||||||
|
|
||||||
|
b.HasIndex(x => new { x.PermissionKey }); |
||||||
|
}); |
||||||
|
|
||||||
|
builder.Entity<MenuGrant>(b => |
||||||
|
{ |
||||||
|
b.ToTable(MenuManagementDbProperties.DbTablePrefix + "MenuGrants", MenuManagementDbProperties.DbSchema); |
||||||
|
b.ConfigureByConvention(); |
||||||
|
|
||||||
|
b.Property(x => x.MenuId).IsRequired(); |
||||||
|
b.Property(x => x.ProviderName).HasMaxLength(MenuGrantConsts.MaxProviderNameLength).IsRequired(); |
||||||
|
b.Property(x => x.ProviderKey).HasMaxLength(MenuGrantConsts.MaxProviderKeyLength).IsRequired(); |
||||||
|
|
||||||
|
b.HasIndex(x => new { x.MenuId, x.ProviderName, x.ProviderKey }); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
using Microsoft.Extensions.DependencyInjection; |
||||||
|
using Volo.Abp.EntityFrameworkCore; |
||||||
|
using Volo.Abp.Modularity; |
||||||
|
using Volo.Abp.PermissionManagement.EntityFrameworkCore; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement.EntityFrameworkCore; |
||||||
|
|
||||||
|
[DependsOn( |
||||||
|
typeof(AbpPermissionManagementEntityFrameworkCoreModule), |
||||||
|
typeof(MenuManagementDomainModule), |
||||||
|
typeof(AbpEntityFrameworkCoreModule) |
||||||
|
)] |
||||||
|
public class MenuManagementEntityFrameworkCoreModule : AbpModule |
||||||
|
{ |
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||||
|
{ |
||||||
|
context.Services.AddAbpDbContext<MenuManagementDbContext>(options => |
||||||
|
{ |
||||||
|
options.AddRepository<Menu, MenuRepository>(); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
using Sanhe.Abp.MenuManagement.EntityFrameworkCore; |
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Threading; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||||
|
using Volo.Abp.EntityFrameworkCore; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuGrantRepository : EfCoreRepository<IMenuManagementDbContext, MenuGrant, Guid>, IMenuGrantRepository |
||||||
|
{ |
||||||
|
public MenuGrantRepository(IDbContextProvider<IMenuManagementDbContext> dbContextProvider) : base(dbContextProvider) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public virtual async Task<MenuGrant> FindAsync(Guid menuId, string providerName, string providerKey, |
||||||
|
CancellationToken cancellationToken = default) |
||||||
|
{ |
||||||
|
return await (await GetDbSetAsync()) |
||||||
|
.FirstOrDefaultAsync(s => |
||||||
|
s.MenuId == menuId && |
||||||
|
s.ProviderName == providerName && |
||||||
|
s.ProviderKey == providerKey, |
||||||
|
GetCancellationToken(cancellationToken) |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual async Task<List<MenuGrant>> GetListAsync(string providerName, string providerKey, |
||||||
|
CancellationToken cancellationToken = default) |
||||||
|
{ |
||||||
|
return await (await GetDbSetAsync()) |
||||||
|
.Where(x => x.ProviderKey == providerKey && x.ProviderName == providerName) |
||||||
|
.ToListAsync(GetCancellationToken(cancellationToken)); |
||||||
|
|
||||||
|
//return await ( |
||||||
|
// from g in DbSet |
||||||
|
// join m in DbContext.Set<Menu>() on g.MenuId equals m.Id |
||||||
|
// where g.ProviderKey == providerKey && g.ProviderName == providerName |
||||||
|
// select new MenuGrantInfoDto |
||||||
|
// { |
||||||
|
// Id = g.MenuId, |
||||||
|
// Name = m.Name, |
||||||
|
// DisplayName = m.DisplayName, |
||||||
|
// PermissionKey = m.PermissionKey, |
||||||
|
// IsGranted = true |
||||||
|
// } |
||||||
|
//).ToListAsync(GetCancellationToken(cancellationToken)); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual async Task<List<MenuGrant>> GetGrantByMenuIdAsync(Guid menuId, bool noTracking = true) |
||||||
|
{ |
||||||
|
var query = (await GetDbSetAsync()).Where(x => x.MenuId == menuId); |
||||||
|
|
||||||
|
if (noTracking) |
||||||
|
{ |
||||||
|
query = query.AsNoTracking(); |
||||||
|
} |
||||||
|
|
||||||
|
return await query.ToListAsync(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
using Sanhe.Abp.MenuManagement.EntityFrameworkCore; |
||||||
|
using System; |
||||||
|
using System.Linq; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||||
|
using Volo.Abp.EntityFrameworkCore; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
public class MenuRepository : EfCoreRepository<IMenuManagementDbContext, Menu, Guid>, IMenuRepository |
||||||
|
{ |
||||||
|
public MenuRepository(IDbContextProvider<IMenuManagementDbContext> dbContextProvider) : base(dbContextProvider) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public override async Task<IQueryable<Menu>> WithDetailsAsync() |
||||||
|
{ |
||||||
|
var queryable = await GetQueryableAsync(); |
||||||
|
|
||||||
|
return queryable.Include(x => x.Parent); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||||
|
</Weavers> |
@ -0,0 +1,16 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||||
|
<Import Project="..\..\..\common.props" /> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<TargetFramework>net6.0</TargetFramework> |
||||||
|
<RootNamespace /> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<ItemGroup> |
||||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpVersion)" /> |
||||||
|
<PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" Version="$(VoloAbpVersion)" /> |
||||||
|
<ProjectReference Include="..\Sanhe.Abp.MenuManagement.Application.Contracts\Sanhe.Abp.MenuManagement.Application.Contracts.csproj" /> |
||||||
|
</ItemGroup> |
||||||
|
</Project> |
@ -0,0 +1,57 @@ |
|||||||
|
using Microsoft.AspNetCore.Mvc; |
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp; |
||||||
|
using Volo.Abp.Application.Dtos; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
[RemoteService] |
||||||
|
[Route("api/menu-management/menus")] |
||||||
|
public class MenuController : MenuManagementController, IMenuAppService |
||||||
|
{ |
||||||
|
private readonly IMenuAppService _menuAppService; |
||||||
|
|
||||||
|
public MenuController(IMenuAppService menuAppService) |
||||||
|
{ |
||||||
|
_menuAppService = menuAppService; |
||||||
|
} |
||||||
|
|
||||||
|
[HttpGet("{id}")] |
||||||
|
public virtual Task<MenuDto> GetAsync(Guid id) |
||||||
|
{ |
||||||
|
return _menuAppService.GetAsync(id); |
||||||
|
} |
||||||
|
|
||||||
|
[HttpGet] |
||||||
|
public virtual Task<PagedResultDto<MenuDto>> GetListAsync(MenuRequestDto input) |
||||||
|
{ |
||||||
|
return _menuAppService.GetListAsync(input); |
||||||
|
} |
||||||
|
|
||||||
|
[HttpPost] |
||||||
|
public virtual Task<MenuDto> CreateAsync(CreateOrUpdateMenuDto input) |
||||||
|
{ |
||||||
|
return _menuAppService.CreateAsync(input); |
||||||
|
} |
||||||
|
|
||||||
|
[HttpPut("{id}")] |
||||||
|
public virtual Task<MenuDto> UpdateAsync(Guid id, CreateOrUpdateMenuDto input) |
||||||
|
{ |
||||||
|
return _menuAppService.UpdateAsync(id, input); |
||||||
|
} |
||||||
|
|
||||||
|
[HttpDelete("{id}")] |
||||||
|
public virtual Task DeleteAsync(Guid id) |
||||||
|
{ |
||||||
|
return _menuAppService.DeleteAsync(id); |
||||||
|
} |
||||||
|
|
||||||
|
[HttpGet("auth-policies")] |
||||||
|
public virtual Task<List<AuthPolicyDto>> GetAuthPolicies() |
||||||
|
{ |
||||||
|
return _menuAppService.GetAuthPolicies(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
using Microsoft.AspNetCore.Mvc; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Volo.Abp; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 菜单分配 |
||||||
|
/// </summary> |
||||||
|
[RemoteService] |
||||||
|
[Route("api/menu-management/menu-grant")] |
||||||
|
public class MenuGrantController : MenuManagementController, IMenuGrantAppService |
||||||
|
{ |
||||||
|
private readonly IMenuGrantAppService _menuGrantAppService; |
||||||
|
|
||||||
|
public MenuGrantController(IMenuGrantAppService menuGrantAppService) |
||||||
|
{ |
||||||
|
_menuGrantAppService = menuGrantAppService; |
||||||
|
} |
||||||
|
|
||||||
|
[HttpGet("list")] |
||||||
|
public virtual Task<GetMenuResultDto> GetListAsync() |
||||||
|
{ |
||||||
|
return _menuGrantAppService.GetListAsync(); |
||||||
|
} |
||||||
|
|
||||||
|
[HttpGet] |
||||||
|
public virtual Task<GetMenuGrantListResultDto> GetAsync(string providerName, string providerKey) |
||||||
|
{ |
||||||
|
return _menuGrantAppService.GetAsync(providerName, providerKey); |
||||||
|
} |
||||||
|
|
||||||
|
[HttpPut] |
||||||
|
public virtual Task UpdateAsync(string providerName, string providerKey, UpdateMenuGrantsDto input) |
||||||
|
{ |
||||||
|
return _menuGrantAppService.UpdateAsync(providerName, providerKey, input); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
using Sanhe.Abp.MenuManagement.Localization; |
||||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
public abstract class MenuManagementController : AbpControllerBase |
||||||
|
{ |
||||||
|
protected MenuManagementController() |
||||||
|
{ |
||||||
|
LocalizationResource = typeof(MenuManagementResource); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
using Localization.Resources.AbpUi; |
||||||
|
using Microsoft.Extensions.DependencyInjection; |
||||||
|
using Sanhe.Abp.MenuManagement.Localization; |
||||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||||
|
using Volo.Abp.Localization; |
||||||
|
using Volo.Abp.Modularity; |
||||||
|
using Volo.Abp.PermissionManagement.HttpApi; |
||||||
|
|
||||||
|
namespace Sanhe.Abp.MenuManagement; |
||||||
|
|
||||||
|
[DependsOn( |
||||||
|
typeof(AbpPermissionManagementHttpApiModule), |
||||||
|
typeof(MenuManagementApplicationContractsModule), |
||||||
|
typeof(AbpAspNetCoreMvcModule))] |
||||||
|
public class MenuManagementHttpApiModule : AbpModule |
||||||
|
{ |
||||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||||
|
{ |
||||||
|
PreConfigure<IMvcBuilder>(mvcBuilder => |
||||||
|
{ |
||||||
|
mvcBuilder.AddApplicationPartIfNotExists(typeof(MenuManagementHttpApiModule).Assembly); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||||
|
{ |
||||||
|
Configure<AbpLocalizationOptions>(options => |
||||||
|
{ |
||||||
|
options.Resources |
||||||
|
.Get<MenuManagementResource>() |
||||||
|
.AddBaseTypes(typeof(AbpUiResource)); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue