Browse Source

vue 菜单

master
guotianliang 3 years ago
parent
commit
6e9218d7ea
  1. 52
      Sanhe.Abp.Framework.sln
  2. 3
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/FodyWeavers.xml
  3. 21
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe.Abp.MenuManagement.Application.Contracts.csproj
  4. 23
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/AuthPolicyDto.cs
  5. 97
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/CreateOrUpdateMenuDto.cs
  6. 44
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/FrontMenu.cs
  7. 10
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuGrantListResultDto.cs
  8. 10
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuResultDto.cs
  9. 16
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuAppService.cs
  10. 13
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuGrantAppService.cs
  11. 63
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuDto.cs
  12. 17
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementApplicationContractsModule.cs
  13. 8
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementRemoteServiceConsts.cs
  14. 14
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuMeta.cs
  15. 14
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuRequestDto.cs
  16. 24
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissionDefinitionProvider.cs
  17. 22
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissions.cs
  18. 20
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantDto.cs
  19. 7
      modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantsDto.cs
  20. 3
      modules/menu-management/Sanhe.Abp.MenuManagement.Application/FodyWeavers.xml
  21. 22
      modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe.Abp.MenuManagement.Application.csproj
  22. 182
      modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuAppService.cs
  23. 215
      modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuGrantAppService.cs
  24. 13
      modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementAppService.cs
  25. 24
      modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationAutoMapperProfile.cs
  26. 26
      modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationModule.cs
  27. 3
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/FodyWeavers.xml
  28. 19
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe.Abp.MenuManagement.Domain.Identity.csproj
  29. 60
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/RoleMenuManagementProvider.cs
  30. 22
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/UserMenuManagementProvider.cs
  31. 24
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/MenuManagementDomainIdentityModule.cs
  32. 3
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/FodyWeavers.xml
  33. 25
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe.Abp.MenuManagement.Domain.Shared.csproj
  34. 9
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/MenuManagementResource.cs
  35. 25
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/en.json
  36. 30
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/zh-Hans.json
  37. 17
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuEnumType.cs
  38. 16
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantConsts.cs
  39. 18
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantInfoDto.cs
  40. 38
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuManagementDomainSharedModule.cs
  41. 21
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuProviderInfo.cs
  42. 3
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/FodyWeavers.xml
  43. 20
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe.Abp.MenuManagement.Domain.csproj
  44. 10
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantChecker.cs
  45. 24
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRepository.cs
  46. 9
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRuntimeCheckerProvider.cs
  47. 25
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManagementProvider.cs
  48. 15
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManager.cs
  49. 10
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuRepository.cs
  50. 65
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IUserMenuGrantChecker.cs
  51. 100
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Menu.cs
  52. 60
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrant.cs
  53. 27
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItem.cs
  54. 65
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItemInvalidator.cs
  55. 59
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantChecker.cs
  56. 19
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantInfo.cs
  57. 8
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantResultEnum.cs
  58. 10
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerContent.cs
  59. 61
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerProvider.cs
  60. 10
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDbProperties.cs
  61. 13
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDomainModule.cs
  62. 14
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementOptions.cs
  63. 81
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementProvider.cs
  64. 116
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManager.cs
  65. 26
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuWithGrantedProviders.cs
  66. 48
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Permission.cs
  67. 63
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/PermissionGroup.cs
  68. 13
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettingDefinitionProvider.cs
  69. 10
      modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettings.cs
  70. 3
      modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/FodyWeavers.xml
  71. 20
      modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe.Abp.MenuManagement.EntityFrameworkCore.csproj
  72. 12
      modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/IMenuManagementDbContext.cs
  73. 25
      modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContext.cs
  74. 43
      modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContextModelCreatingExtensions.cs
  75. 22
      modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementEntityFrameworkCoreModule.cs
  76. 66
      modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuGrantRepository.cs
  77. 25
      modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuRepository.cs
  78. 3
      modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/FodyWeavers.xml
  79. 16
      modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe.Abp.MenuManagement.HttpApi.csproj
  80. 57
      modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuController.cs
  81. 39
      modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuGrantController.cs
  82. 12
      modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementController.cs
  83. 34
      modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementHttpApiModule.cs

52
Sanhe.Abp.Framework.sln

@ -91,6 +91,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "elasticsearch", "elasticsea
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.Elasticsearch", "modules\elasticsearch\Sanhe.Abp.Elasticsearch\Sanhe.Abp.Elasticsearch.csproj", "{3E1DA541-4D48-47A1-93FA-3D75BCB078F3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.Elasticsearch", "modules\elasticsearch\Sanhe.Abp.Elasticsearch\Sanhe.Abp.Elasticsearch.csproj", "{3E1DA541-4D48-47A1-93FA-3D75BCB078F3}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "menu-management", "menu-management", "{1D9012F7-AAA3-49E0-9852-4A97FFB26E8C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.MenuManagement.Domain", "modules\menu-management\Sanhe.Abp.MenuManagement.Domain\Sanhe.Abp.MenuManagement.Domain.csproj", "{FC204CCD-E64A-4388-86DF-5366E181C811}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.MenuManagement.Domain.Identity", "modules\menu-management\Sanhe.Abp.MenuManagement.Domain.Identity\Sanhe.Abp.MenuManagement.Domain.Identity.csproj", "{CE313A6B-8C92-4939-9853-54FFAF553E7D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.MenuManagement.Domain.Shared", "modules\menu-management\Sanhe.Abp.MenuManagement.Domain.Shared\Sanhe.Abp.MenuManagement.Domain.Shared.csproj", "{89719844-E5AE-4FF9-B930-77ADF4B6404F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.MenuManagement.Application.Contracts", "modules\menu-management\Sanhe.Abp.MenuManagement.Application.Contracts\Sanhe.Abp.MenuManagement.Application.Contracts.csproj", "{F9F99C94-2558-4B29-9192-61072A240CA1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.MenuManagement.Application", "modules\menu-management\Sanhe.Abp.MenuManagement.Application\Sanhe.Abp.MenuManagement.Application.csproj", "{B234FA38-6CC5-44D1-8D4F-926E8575C989}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.MenuManagement.EntityFrameworkCore", "modules\menu-management\Sanhe.Abp.MenuManagement.EntityFrameworkCore\Sanhe.Abp.MenuManagement.EntityFrameworkCore.csproj", "{F60BA528-E8FE-465D-BAED-EAC48DE57847}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.MenuManagement.HttpApi", "modules\menu-management\Sanhe.Abp.MenuManagement.HttpApi\Sanhe.Abp.MenuManagement.HttpApi.csproj", "{4A545053-9CD6-4578-92AF-1637AAC79F80}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -221,6 +237,34 @@ Global
{3E1DA541-4D48-47A1-93FA-3D75BCB078F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {3E1DA541-4D48-47A1-93FA-3D75BCB078F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E1DA541-4D48-47A1-93FA-3D75BCB078F3}.Release|Any CPU.ActiveCfg = Release|Any CPU {3E1DA541-4D48-47A1-93FA-3D75BCB078F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E1DA541-4D48-47A1-93FA-3D75BCB078F3}.Release|Any CPU.Build.0 = Release|Any CPU {3E1DA541-4D48-47A1-93FA-3D75BCB078F3}.Release|Any CPU.Build.0 = Release|Any CPU
{FC204CCD-E64A-4388-86DF-5366E181C811}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC204CCD-E64A-4388-86DF-5366E181C811}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC204CCD-E64A-4388-86DF-5366E181C811}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC204CCD-E64A-4388-86DF-5366E181C811}.Release|Any CPU.Build.0 = Release|Any CPU
{CE313A6B-8C92-4939-9853-54FFAF553E7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CE313A6B-8C92-4939-9853-54FFAF553E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CE313A6B-8C92-4939-9853-54FFAF553E7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CE313A6B-8C92-4939-9853-54FFAF553E7D}.Release|Any CPU.Build.0 = Release|Any CPU
{89719844-E5AE-4FF9-B930-77ADF4B6404F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89719844-E5AE-4FF9-B930-77ADF4B6404F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89719844-E5AE-4FF9-B930-77ADF4B6404F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{89719844-E5AE-4FF9-B930-77ADF4B6404F}.Release|Any CPU.Build.0 = Release|Any CPU
{F9F99C94-2558-4B29-9192-61072A240CA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F9F99C94-2558-4B29-9192-61072A240CA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F9F99C94-2558-4B29-9192-61072A240CA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F9F99C94-2558-4B29-9192-61072A240CA1}.Release|Any CPU.Build.0 = Release|Any CPU
{B234FA38-6CC5-44D1-8D4F-926E8575C989}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B234FA38-6CC5-44D1-8D4F-926E8575C989}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B234FA38-6CC5-44D1-8D4F-926E8575C989}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B234FA38-6CC5-44D1-8D4F-926E8575C989}.Release|Any CPU.Build.0 = Release|Any CPU
{F60BA528-E8FE-465D-BAED-EAC48DE57847}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F60BA528-E8FE-465D-BAED-EAC48DE57847}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F60BA528-E8FE-465D-BAED-EAC48DE57847}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F60BA528-E8FE-465D-BAED-EAC48DE57847}.Release|Any CPU.Build.0 = Release|Any CPU
{4A545053-9CD6-4578-92AF-1637AAC79F80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A545053-9CD6-4578-92AF-1637AAC79F80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A545053-9CD6-4578-92AF-1637AAC79F80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A545053-9CD6-4578-92AF-1637AAC79F80}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -264,6 +308,14 @@ Global
{464E3A2C-BBEB-4CD9-BAB8-A51D6283940A} = {2A768109-31B7-4C52-928C-3023DAB9F254} {464E3A2C-BBEB-4CD9-BAB8-A51D6283940A} = {2A768109-31B7-4C52-928C-3023DAB9F254}
{449F764E-D3D5-4DFD-8707-2A378CF44C64} = {F5F5D604-531B-4B57-A88E-C9C5CEEC55D7} {449F764E-D3D5-4DFD-8707-2A378CF44C64} = {F5F5D604-531B-4B57-A88E-C9C5CEEC55D7}
{3E1DA541-4D48-47A1-93FA-3D75BCB078F3} = {449F764E-D3D5-4DFD-8707-2A378CF44C64} {3E1DA541-4D48-47A1-93FA-3D75BCB078F3} = {449F764E-D3D5-4DFD-8707-2A378CF44C64}
{1D9012F7-AAA3-49E0-9852-4A97FFB26E8C} = {F5F5D604-531B-4B57-A88E-C9C5CEEC55D7}
{FC204CCD-E64A-4388-86DF-5366E181C811} = {1D9012F7-AAA3-49E0-9852-4A97FFB26E8C}
{CE313A6B-8C92-4939-9853-54FFAF553E7D} = {1D9012F7-AAA3-49E0-9852-4A97FFB26E8C}
{89719844-E5AE-4FF9-B930-77ADF4B6404F} = {1D9012F7-AAA3-49E0-9852-4A97FFB26E8C}
{F9F99C94-2558-4B29-9192-61072A240CA1} = {1D9012F7-AAA3-49E0-9852-4A97FFB26E8C}
{B234FA38-6CC5-44D1-8D4F-926E8575C989} = {1D9012F7-AAA3-49E0-9852-4A97FFB26E8C}
{F60BA528-E8FE-465D-BAED-EAC48DE57847} = {1D9012F7-AAA3-49E0-9852-4A97FFB26E8C}
{4A545053-9CD6-4578-92AF-1637AAC79F80} = {1D9012F7-AAA3-49E0-9852-4A97FFB26E8C}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AB69BFDE-9DDB-4D16-8CB8-72472C0319CD} SolutionGuid = {AB69BFDE-9DDB-4D16-8CB8-72472C0319CD}

3
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

21
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe.Abp.MenuManagement.Application.Contracts.csproj

@ -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>

23
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/AuthPolicyDto.cs

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

97
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/CreateOrUpdateMenuDto.cs

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

44
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/FrontMenu.cs

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

10
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuGrantListResultDto.cs

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

10
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuResultDto.cs

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

16
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuAppService.cs

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

13
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuGrantAppService.cs

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

63
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuDto.cs

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

17
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementApplicationContractsModule.cs

@ -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
{
}

8
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementRemoteServiceConsts.cs

@ -0,0 +1,8 @@
namespace Sanhe.Abp.MenuManagement;
public class MenuManagementRemoteServiceConsts
{
public const string RemoteServiceName = "MenuManagement";
public const string ModuleName = "menuManagement";
}

14
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuMeta.cs

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

14
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuRequestDto.cs

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

24
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissionDefinitionProvider.cs

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

22
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissions.cs

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

20
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantDto.cs

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

7
modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantsDto.cs

@ -0,0 +1,7 @@
namespace Sanhe.Abp.MenuManagement
{
public class UpdateMenuGrantsDto
{
public UpdateMenuGrantDto[] Menus { get; set; }
}
}

3
modules/menu-management/Sanhe.Abp.MenuManagement.Application/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

22
modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe.Abp.MenuManagement.Application.csproj

@ -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>

182
modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuAppService.cs

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

215
modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuGrantAppService.cs

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

13
modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementAppService.cs

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

24
modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationAutoMapperProfile.cs

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

26
modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationModule.cs

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

3
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait />
</Weavers>

19
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe.Abp.MenuManagement.Domain.Identity.csproj

@ -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>

60
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/RoleMenuManagementProvider.cs

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

22
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/UserMenuManagementProvider.cs

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

24
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/MenuManagementDomainIdentityModule.cs

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

3
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

25
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe.Abp.MenuManagement.Domain.Shared.csproj

@ -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>

9
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/MenuManagementResource.cs

@ -0,0 +1,9 @@
using Volo.Abp.Localization;
namespace Sanhe.Abp.MenuManagement.Localization;
[LocalizationResourceName("MenuManagement")]
public class MenuManagementResource
{
}

25
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/en.json

@ -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"
}
}

30
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/zh-Hans.json

@ -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": "创建权限"
}
}

17
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuEnumType.cs

@ -0,0 +1,17 @@
namespace Sanhe.Abp.MenuManagement
{
/// <summary>
/// 菜单类型
/// </summary>
public enum MenuEnumType
{
/// <summary>
/// 菜单
/// </summary>
Menu,
/// <summary>
/// 权限
/// </summary>
Permission
}
}

16
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantConsts.cs

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

18
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantInfoDto.cs

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

38
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuManagementDomainSharedModule.cs

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

21
modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuProviderInfo.cs

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

3
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

20
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe.Abp.MenuManagement.Domain.csproj

@ -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>

10
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantChecker.cs

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

24
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRepository.cs

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

9
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRuntimeCheckerProvider.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Sanhe.Abp.MenuManagement
{
public interface IMenuGrantRuntimeCheckerProvider
{
Task<MenuGrantResultEnum> CheckAsync(MenuGrantRuntimeCheckerContent context);
}
}

25
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManagementProvider.cs

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

15
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManager.cs

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

10
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuRepository.cs

@ -0,0 +1,10 @@
using System;
using Volo.Abp.Domain.Repositories;
namespace Sanhe.Abp.MenuManagement
{
public interface IMenuRepository : IRepository<Menu, Guid>
{
}
}

65
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IUserMenuGrantChecker.cs

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

100
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Menu.cs

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

60
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrant.cs

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

27
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItem.cs

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

65
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItemInvalidator.cs

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

59
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantChecker.cs

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

19
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantInfo.cs

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

8
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantResultEnum.cs

@ -0,0 +1,8 @@
namespace Sanhe.Abp.MenuManagement
{
public enum MenuGrantResultEnum
{
Undefined,
Granted
}
}

10
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerContent.cs

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

61
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerProvider.cs

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

10
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDbProperties.cs

@ -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";
}

13
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDomainModule.cs

@ -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
{
}

14
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementOptions.cs

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

81
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementProvider.cs

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

116
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManager.cs

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

26
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuWithGrantedProviders.cs

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

48
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Permission.cs

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

63
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/PermissionGroup.cs

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

13
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettingDefinitionProvider.cs

@ -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.
*/
}
}

10
modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettings.cs

@ -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";
*/
}

3
modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

20
modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe.Abp.MenuManagement.EntityFrameworkCore.csproj

@ -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>

12
modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/IMenuManagementDbContext.cs

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

25
modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContext.cs

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

43
modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContextModelCreatingExtensions.cs

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

22
modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementEntityFrameworkCoreModule.cs

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

66
modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuGrantRepository.cs

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

25
modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuRepository.cs

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

3
modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

16
modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe.Abp.MenuManagement.HttpApi.csproj

@ -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>

57
modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuController.cs

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

39
modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuGrantController.cs

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

12
modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementController.cs

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

34
modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementHttpApiModule.cs

@ -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…
Cancel
Save