From 6e9218d7ea47390bd789b1469bbeecd4fcbe4bdd Mon Sep 17 00:00:00 2001 From: guotianliang <1265346495@qq.com> Date: Tue, 10 May 2022 14:24:21 +0800 Subject: [PATCH] =?UTF-8?q?vue=20=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sanhe.Abp.Framework.sln | 52 +++++ .../FodyWeavers.xml | 3 + ...enuManagement.Application.Contracts.csproj | 21 ++ .../Sanhe/Abp/MenuManagement/AuthPolicyDto.cs | 23 ++ .../MenuManagement/CreateOrUpdateMenuDto.cs | 97 ++++++++ .../Sanhe/Abp/MenuManagement/FrontMenu.cs | 44 ++++ .../GetMenuGrantListResultDto.cs | 10 + .../Abp/MenuManagement/GetMenuResultDto.cs | 10 + .../Abp/MenuManagement/IMenuAppService.cs | 16 ++ .../MenuManagement/IMenuGrantAppService.cs | 13 ++ .../Sanhe/Abp/MenuManagement/MenuDto.cs | 63 +++++ ...enuManagementApplicationContractsModule.cs | 17 ++ .../MenuManagementRemoteServiceConsts.cs | 8 + .../Sanhe/Abp/MenuManagement/MenuMeta.cs | 14 ++ .../Abp/MenuManagement/MenuRequestDto.cs | 14 ++ ...uManagementPermissionDefinitionProvider.cs | 24 ++ .../Permissions/MenuManagementPermissions.cs | 22 ++ .../Abp/MenuManagement/UpdateMenuGrantDto.cs | 20 ++ .../Abp/MenuManagement/UpdateMenuGrantsDto.cs | 7 + .../FodyWeavers.xml | 3 + ...anhe.Abp.MenuManagement.Application.csproj | 22 ++ .../Abp/MenuManagement/MenuAppService.cs | 182 +++++++++++++++ .../Abp/MenuManagement/MenuGrantAppService.cs | 215 ++++++++++++++++++ .../MenuManagementAppService.cs | 13 ++ ...uManagementApplicationAutoMapperProfile.cs | 24 ++ .../MenuManagementApplicationModule.cs | 26 +++ .../FodyWeavers.xml | 3 + ....Abp.MenuManagement.Domain.Identity.csproj | 19 ++ .../Identity/RoleMenuManagementProvider.cs | 60 +++++ .../Identity/UserMenuManagementProvider.cs | 22 ++ .../MenuManagementDomainIdentityModule.cs | 24 ++ .../FodyWeavers.xml | 3 + ...he.Abp.MenuManagement.Domain.Shared.csproj | 25 ++ .../Localization/MenuManagementResource.cs | 9 + .../Localization/Resources/en.json | 25 ++ .../Localization/Resources/zh-Hans.json | 30 +++ .../Sanhe/Abp/MenuManagement/MenuEnumType.cs | 17 ++ .../Abp/MenuManagement/MenuGrantConsts.cs | 16 ++ .../Abp/MenuManagement/MenuGrantInfoDto.cs | 18 ++ .../MenuManagementDomainSharedModule.cs | 38 ++++ .../Abp/MenuManagement/MenuProviderInfo.cs | 21 ++ .../FodyWeavers.xml | 3 + .../Sanhe.Abp.MenuManagement.Domain.csproj | 20 ++ .../Abp/MenuManagement/IMenuGrantChecker.cs | 10 + .../MenuManagement/IMenuGrantRepository.cs | 24 ++ .../IMenuGrantRuntimeCheckerProvider.cs | 9 + .../MenuManagement/IMenuManagementProvider.cs | 25 ++ .../Sanhe/Abp/MenuManagement/IMenuManager.cs | 15 ++ .../Abp/MenuManagement/IMenuRepository.cs | 10 + .../MenuManagement/IUserMenuGrantChecker.cs | 65 ++++++ .../Sanhe/Abp/MenuManagement/Menu.cs | 100 ++++++++ .../Sanhe/Abp/MenuManagement/MenuGrant.cs | 60 +++++ .../Abp/MenuManagement/MenuGrantCacheItem.cs | 27 +++ .../MenuGrantCacheItemInvalidator.cs | 65 ++++++ .../Abp/MenuManagement/MenuGrantChecker.cs | 59 +++++ .../Sanhe/Abp/MenuManagement/MenuGrantInfo.cs | 19 ++ .../Abp/MenuManagement/MenuGrantResultEnum.cs | 8 + .../MenuGrantRuntimeCheckerContent.cs | 10 + .../MenuGrantRuntimeCheckerProvider.cs | 61 +++++ .../MenuManagementDbProperties.cs | 10 + .../MenuManagementDomainModule.cs | 13 ++ .../MenuManagement/MenuManagementOptions.cs | 14 ++ .../MenuManagement/MenuManagementProvider.cs | 81 +++++++ .../Sanhe/Abp/MenuManagement/MenuManager.cs | 116 ++++++++++ .../MenuWithGrantedProviders.cs | 26 +++ .../Sanhe/Abp/MenuManagement/Permission.cs | 48 ++++ .../Abp/MenuManagement/PermissionGroup.cs | 63 +++++ ...MenuManagementSettingDefinitionProvider.cs | 13 ++ .../Settings/MenuManagementSettings.cs | 10 + .../FodyWeavers.xml | 3 + ....MenuManagement.EntityFrameworkCore.csproj | 20 ++ .../IMenuManagementDbContext.cs | 12 + .../MenuManagementDbContext.cs | 25 ++ ...agementDbContextModelCreatingExtensions.cs | 43 ++++ ...MenuManagementEntityFrameworkCoreModule.cs | 22 ++ .../Abp/MenuManagement/MenuGrantRepository.cs | 66 ++++++ .../Abp/MenuManagement/MenuRepository.cs | 25 ++ .../FodyWeavers.xml | 3 + .../Sanhe.Abp.MenuManagement.HttpApi.csproj | 16 ++ .../Abp/MenuManagement/MenuController.cs | 57 +++++ .../Abp/MenuManagement/MenuGrantController.cs | 39 ++++ .../MenuManagementController.cs | 12 + .../MenuManagementHttpApiModule.cs | 34 +++ 83 files changed, 2654 insertions(+) create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/FodyWeavers.xml create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe.Abp.MenuManagement.Application.Contracts.csproj create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/AuthPolicyDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/CreateOrUpdateMenuDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/FrontMenu.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuGrantListResultDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuResultDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuAppService.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuGrantAppService.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementApplicationContractsModule.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementRemoteServiceConsts.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuMeta.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuRequestDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissionDefinitionProvider.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissions.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantsDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application/FodyWeavers.xml create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe.Abp.MenuManagement.Application.csproj create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuAppService.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuGrantAppService.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementAppService.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationAutoMapperProfile.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationModule.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/FodyWeavers.xml create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe.Abp.MenuManagement.Domain.Identity.csproj create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/RoleMenuManagementProvider.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/UserMenuManagementProvider.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/MenuManagementDomainIdentityModule.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/FodyWeavers.xml create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe.Abp.MenuManagement.Domain.Shared.csproj create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/MenuManagementResource.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/en.json create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/zh-Hans.json create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuEnumType.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantConsts.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantInfoDto.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuManagementDomainSharedModule.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuProviderInfo.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/FodyWeavers.xml create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe.Abp.MenuManagement.Domain.csproj create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantChecker.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRepository.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRuntimeCheckerProvider.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManagementProvider.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManager.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuRepository.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IUserMenuGrantChecker.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Menu.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrant.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItem.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItemInvalidator.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantChecker.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantInfo.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantResultEnum.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerContent.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerProvider.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDbProperties.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDomainModule.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementOptions.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementProvider.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManager.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuWithGrantedProviders.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Permission.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/PermissionGroup.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettingDefinitionProvider.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettings.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/FodyWeavers.xml create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe.Abp.MenuManagement.EntityFrameworkCore.csproj create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/IMenuManagementDbContext.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContext.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContextModelCreatingExtensions.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementEntityFrameworkCoreModule.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuGrantRepository.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuRepository.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/FodyWeavers.xml create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe.Abp.MenuManagement.HttpApi.csproj create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuController.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuGrantController.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementController.cs create mode 100644 modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementHttpApiModule.cs diff --git a/Sanhe.Abp.Framework.sln b/Sanhe.Abp.Framework.sln index ad240d5..0938217 100644 --- a/Sanhe.Abp.Framework.sln +++ b/Sanhe.Abp.Framework.sln @@ -91,6 +91,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "elasticsearch", "elasticsea EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.Elasticsearch", "modules\elasticsearch\Sanhe.Abp.Elasticsearch\Sanhe.Abp.Elasticsearch.csproj", "{3E1DA541-4D48-47A1-93FA-3D75BCB078F3}" 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 GlobalSection(SolutionConfigurationPlatforms) = preSolution 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}.Release|Any CPU.ActiveCfg = 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 GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -264,6 +308,14 @@ Global {464E3A2C-BBEB-4CD9-BAB8-A51D6283940A} = {2A768109-31B7-4C52-928C-3023DAB9F254} {449F764E-D3D5-4DFD-8707-2A378CF44C64} = {F5F5D604-531B-4B57-A88E-C9C5CEEC55D7} {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 GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AB69BFDE-9DDB-4D16-8CB8-72472C0319CD} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/FodyWeavers.xml b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/FodyWeavers.xml new file mode 100644 index 0000000..1715698 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe.Abp.MenuManagement.Application.Contracts.csproj b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe.Abp.MenuManagement.Application.Contracts.csproj new file mode 100644 index 0000000..c705c92 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe.Abp.MenuManagement.Application.Contracts.csproj @@ -0,0 +1,21 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + + diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/AuthPolicyDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/AuthPolicyDto.cs new file mode 100644 index 0000000..77c1b53 --- /dev/null +++ b/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 +{ + /// + /// 授权策略 + /// + public class AuthPolicyDto + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 显示名称 + /// + public string DisplayName { get; set; } + /// + /// 子策略 + /// + public List Children { get; set; } = new List(); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/CreateOrUpdateMenuDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/CreateOrUpdateMenuDto.cs new file mode 100644 index 0000000..6924cfa --- /dev/null +++ b/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 +{ + /// + /// 创建修改菜单 + /// + public class CreateOrUpdateMenuDto : EntityDto, IValidatableObject + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 显示名称 + /// + public string DisplayName { get; set; } + /// + /// 组件路径 + /// + public string ComponentPath { get; set; } + /// + /// 路由路径 + /// + public string RouterPath { get; set; } + /// + /// 父Id + /// + public Guid? ParentId { get; set; } + /// + /// 菜单类型 + /// + public MenuEnumType MenuType { get; set; } + /// + /// 图标 + /// + public string Icon { get; set; } + /// + /// 排序 + /// + public string Sort { get; set; } + /// + /// window.open _blank + /// + public string TargetUrl { get; set; } + /// + /// 此菜单关联的权限key + /// + public string PermissionKey { get; set; } + /// + /// 表示多租户应用程序中的所属方 + /// + public MultiTenancySides MultiTenancySide { get; set; } + + public IEnumerable 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" }); + } + } + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/FrontMenu.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/FrontMenu.cs new file mode 100644 index 0000000..f0764a0 --- /dev/null +++ b/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 +{ + /// + /// 前端菜单 + /// + public class FrontMenu + { + /// + /// Id + /// + public Guid Id { get; set; } + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 组件 + /// + public string Component { get; set; } + /// + /// 路径 + /// + public string Path { get; set; } + /// + /// window.open _blank + /// + public string TargetUrl { get; set; } + /// + /// 此菜单关联的权限key. + /// + public string PermissionKey { get; set; } + /// + /// 菜单标签 + /// + public MenuMeta Meta { get; set; } + /// + /// 子菜单 + /// + public List Children { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuGrantListResultDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuGrantListResultDto.cs new file mode 100644 index 0000000..a8b03a0 --- /dev/null +++ b/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 MenuGrants { get; set; } + public List Menus { get; set; } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuResultDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/GetMenuResultDto.cs new file mode 100644 index 0000000..b0009fa --- /dev/null +++ b/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 PermissionGrants { get; set; } + public List Menus { get; set; } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuAppService.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuAppService.cs new file mode 100644 index 0000000..339a666 --- /dev/null +++ b/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 + { + /// + /// 获取授权策略 + /// + /// + Task> GetAuthPolicies(); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuGrantAppService.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/IMenuGrantAppService.cs new file mode 100644 index 0000000..44c3a97 --- /dev/null +++ b/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 GetListAsync(); + Task GetAsync([NotNull] string providerName, [NotNull] string providerKey); + Task UpdateAsync([NotNull] string providerName, [NotNull] string providerKey, UpdateMenuGrantsDto input); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuDto.cs new file mode 100644 index 0000000..bbc279f --- /dev/null +++ b/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 + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 显示名称 + /// + public string DisplayName { get; set; } + /// + /// 菜单类型 + /// + public MenuEnumType MenuType { get; set; } + /// + /// 组件路径 + /// + public string ComponentPath { get; set; } + /// + /// 路由路径 + /// + public string RouterPath { get; set; } + /// + /// 父级显示名称 + /// + public string ParentDisplayName { get; set; } + /// + /// 父Id + /// + public Guid? ParentId { get; set; } + /// + /// 图标 + /// + public string Icon { get; set; } + /// + /// 排序 + /// + public string Sort { get; set; } + /// + /// window.open _blank + /// + public string TargetUrl { get; set; } + /// + /// 此菜单关联的权限key + /// + public string PermissionKey { get; set; } + /// + /// 表示多租户应用程序中的所属方 + /// + public MultiTenancySides MultiTenancySide { get; set; } + /// + /// 子菜单 + /// + public List Children { get; set; } = new List(); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementApplicationContractsModule.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementApplicationContractsModule.cs new file mode 100644 index 0000000..eb814d3 --- /dev/null +++ b/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 +{ + +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementRemoteServiceConsts.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuManagementRemoteServiceConsts.cs new file mode 100644 index 0000000..4f13142 --- /dev/null +++ b/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"; +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuMeta.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuMeta.cs new file mode 100644 index 0000000..3fa2266 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuMeta.cs @@ -0,0 +1,14 @@ +namespace Sanhe.Abp.MenuManagement +{ + public class MenuMeta + { + /// + /// 标题 + /// + public string Title { get; set; } + /// + /// 图标 + /// + public string Icon { get; set; } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuRequestDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuRequestDto.cs new file mode 100644 index 0000000..c684931 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/MenuRequestDto.cs @@ -0,0 +1,14 @@ +namespace Sanhe.Abp.MenuManagement +{ + public class MenuRequestDto + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 类型 + /// + public MenuEnumType? Type { get; set; } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissionDefinitionProvider.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissionDefinitionProvider.cs new file mode 100644 index 0000000..e4d3b4b --- /dev/null +++ b/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(name); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissions.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/Permissions/MenuManagementPermissions.cs new file mode 100644 index 0000000..3f7a6d9 --- /dev/null +++ b/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)); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantDto.cs new file mode 100644 index 0000000..7533a55 --- /dev/null +++ b/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 + { + /// + /// 菜单Id + /// + public Guid Id { get; set; } + /// + /// 权限key + /// + public string PermissionKey { get; set; } + /// + /// 是否分配 + /// + public bool IsGranted { get; set; } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantsDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application.Contracts/Sanhe/Abp/MenuManagement/UpdateMenuGrantsDto.cs new file mode 100644 index 0000000..fae65f0 --- /dev/null +++ b/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; } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application/FodyWeavers.xml b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/FodyWeavers.xml new file mode 100644 index 0000000..1715698 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe.Abp.MenuManagement.Application.csproj b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe.Abp.MenuManagement.Application.csproj new file mode 100644 index 0000000..52f6b9f --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe.Abp.MenuManagement.Application.csproj @@ -0,0 +1,22 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + + + diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuAppService.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuAppService.cs new file mode 100644 index 0000000..0b12f4a --- /dev/null +++ b/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, + IMenuAppService + { + private readonly IPermissionDefinitionManager _permissionDefinitionManager; + private readonly IMenuManager _menuManager; + private readonly IStringLocalizerFactory _stringLocalizerFactory; + + public MenuAppService( + IRepository repository, + IPermissionDefinitionManager permissionDefinitionManager, + IMenuManager menuManager, + IStringLocalizerFactory stringLocalizerFactory + ) : base(repository) + { + _permissionDefinitionManager = permissionDefinitionManager; + _menuManager = menuManager; + _stringLocalizerFactory = stringLocalizerFactory; + } + + protected override string GetListPolicyName => MenuManagementPermissions.Menus.Default; + protected override string CreatePolicyName => MenuManagementPermissions.Menus.Create; + protected override string UpdatePolicyName => MenuManagementPermissions.Menus.Update; + protected override string DeletePolicyName => MenuManagementPermissions.Menus.Delete; + + public override async Task UpdateAsync(Guid id, CreateOrUpdateMenuDto input) + { + await PermissionChecker(input.PermissionKey, id); + + // 当更新菜单权限时,同时刷 PermissionGrant + var menu = await GetEntityByIdAsync(id); + if (menu.PermissionKey != input.PermissionKey) + { + await _menuManager.UpdatePermissionGrantAsync(id, menu.PermissionKey, input.PermissionKey); + } + + return await base.UpdateAsync(id, input); + } + + public virtual Task> GetAuthPolicies() + { + var result = new List(); + var groups = _permissionDefinitionManager.GetGroups(); + var multiTenancySide = CurrentTenant.GetMultiTenancySide(); + foreach (var group in groups) + { + if (group.Permissions.Count == 0) + { + continue; + } + + foreach (var permission in group.Permissions) + { + if (multiTenancySide != MultiTenancySides.Host && + !permission.MultiTenancySide.HasFlag(multiTenancySide)) + { + continue; + } + + var policy = new AuthPolicyDto() + { + Name = permission.Name, + DisplayName = permission.DisplayName.Localize(_stringLocalizerFactory), + Children = new List + { + new AuthPolicyDto + { + Name = permission.Name, + DisplayName = permission.DisplayName.Localize(_stringLocalizerFactory) + } + } + }; + result.Add(policy); + + foreach (var c in permission.Children) + { + if (multiTenancySide != MultiTenancySides.Host && + !c.MultiTenancySide.HasFlag(multiTenancySide)) + { + continue; + } + + policy.Children.Add(new AuthPolicyDto + { + Name = c.Name, + DisplayName = c.DisplayName.Localize(_stringLocalizerFactory) + }); + } + } + } + + return Task.FromResult(result); + } + + public override async Task CreateAsync(CreateOrUpdateMenuDto input) + { + await PermissionChecker(input.PermissionKey); + return await base.CreateAsync(input); + } + + public override async Task> GetListAsync(MenuRequestDto input) + { + //await CheckGetListPolicyAsync(); + var queryable = await Repository.GetQueryableAsync(); + var allMenus = queryable + .WhereIf(input.Type.HasValue, m => m.MenuType == input.Type) + .WhereIf(!input.Name.IsNullOrWhiteSpace(), m => m.DisplayName.Contains(input.Name)) + .ToList(); + + var root = allMenus + .Where(x => !x.ParentId.HasValue) // 没有parentId + .Union( + // 有parentId,但是“allMenus"中不存在他的Parent。 + allMenus.Where(x => x.ParentId.HasValue).Where(x => allMenus.All(y => x.ParentId != y.Id)) + ) + .OrderBy(x => x.Sort); + + var menuDtos = new List(); + foreach (var menu in root) + { + var dto = ObjectMapper.Map(menu); + menuDtos.Add(dto); + // AddChildrenMenuRecursively(dto, allMenus); + + SortChildrenMenu(dto); + } + + return new PagedResultDto(allMenus.Count, menuDtos); + } + + private async Task PermissionChecker(string permissionName, Guid? menuId = null) + { + if (!permissionName.IsNullOrWhiteSpace()) + { + var permission = _permissionDefinitionManager.GetOrNull(permissionName); + if (permission == null) + { + throw new UserFriendlyException($"未知的权限:“{permissionName}”。"); + } + + var menu = await Repository.FirstOrDefaultAsync(x => x.PermissionKey == permissionName && x.Id != menuId); + if (menu != null) + { + throw new UserFriendlyException($"权限已经被菜单“{menu.DisplayName}”绑定。"); + } + } + } + + private void SortChildrenMenu(MenuDto dto) + { + dto.Children.Sort((a, b) => string.Compare(a.Sort, b.Sort, StringComparison.Ordinal)); + dto.Children.ForEach(SortChildrenMenu); + } + + private void AddChildrenMenuRecursively(MenuDto parent, List allMenus) + { + foreach (var menu in allMenus.Where(x => x.ParentId == parent.Id).OrderBy(x => x.Sort)) + { + var dto = ObjectMapper.Map(menu); + parent.Children.Add(dto); + + AddChildrenMenuRecursively(dto, allMenus); + } + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuGrantAppService.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuGrantAppService.cs new file mode 100644 index 0000000..124bc0b --- /dev/null +++ b/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 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 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(); + foreach (var menu in rootMenus) + { + var isGranted = await _userMenuGrantChecker.CheckAsync(_principalAccessor.Principal, menu); + if (isGranted) + { + var dto = ObjectMapper.Map(menu); + menuDtos.Add(dto); + await FilterChildrenMenuRecursivelyAsync(menu, dto); + } + } + + var permissionGrants = new List(); + 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 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 InternalGetAsync(string providerName, string providerKey) + { + var allMenus = (await _menuRepository.GetQueryableAsync()).ToList(); + var multiTenancySide = CurrentTenant.GetMultiTenancySide(); + + var menuGrants = new List(); + + 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(); + 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(); + foreach (var menu in parent.Children) + { + if (await _userMenuGrantChecker.CheckAsync(_principalAccessor.Principal, menu)) + { + var dto = ObjectMapper.Map(menu); + vueMenu.Children.Add(dto); + await FilterChildrenMenuRecursivelyAsync(menu, dto); + } + } + } + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementAppService.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementAppService.cs new file mode 100644 index 0000000..3757a94 --- /dev/null +++ b/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); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationAutoMapperProfile.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..828c91a --- /dev/null +++ b/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(); + CreateMap(); + CreateMap() + .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 + }); + }); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationModule.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Application/Sanhe/Abp/MenuManagement/MenuManagementApplicationModule.cs new file mode 100644 index 0000000..37b19ed --- /dev/null +++ b/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(); + Configure(options => + { + options.AddMaps(); + }); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/FodyWeavers.xml b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/FodyWeavers.xml new file mode 100644 index 0000000..00e1d9a --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe.Abp.MenuManagement.Domain.Identity.csproj b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe.Abp.MenuManagement.Domain.Identity.csproj new file mode 100644 index 0000000..ef0fc3b --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe.Abp.MenuManagement.Domain.Identity.csproj @@ -0,0 +1,19 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/RoleMenuManagementProvider.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/RoleMenuManagementProvider.cs new file mode 100644 index 0000000..b30a840 --- /dev/null +++ b/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 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; + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/UserMenuManagementProvider.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/Identity/UserMenuManagementProvider.cs new file mode 100644 index 0000000..21c6238 --- /dev/null +++ b/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; + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/MenuManagementDomainIdentityModule.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Identity/Sanhe/Abp/MenuManagement/MenuManagementDomainIdentityModule.cs new file mode 100644 index 0000000..68cae90 --- /dev/null +++ b/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(options => + { + options.ManagementProviders.Add(); + options.ManagementProviders.Add(); + }); + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/FodyWeavers.xml b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/FodyWeavers.xml new file mode 100644 index 0000000..1715698 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe.Abp.MenuManagement.Domain.Shared.csproj b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe.Abp.MenuManagement.Domain.Shared.csproj new file mode 100644 index 0000000..3666600 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe.Abp.MenuManagement.Domain.Shared.csproj @@ -0,0 +1,25 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/MenuManagementResource.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/MenuManagementResource.cs new file mode 100644 index 0000000..ad97210 --- /dev/null +++ b/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 +{ + +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/en.json b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/en.json new file mode 100644 index 0000000..8deaa83 --- /dev/null +++ b/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" + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/zh-Hans.json b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/Localization/Resources/zh-Hans.json new file mode 100644 index 0000000..2a42f43 --- /dev/null +++ b/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": "创建权限" + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuEnumType.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuEnumType.cs new file mode 100644 index 0000000..2548920 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuEnumType.cs @@ -0,0 +1,17 @@ +namespace Sanhe.Abp.MenuManagement +{ + /// + /// 菜单类型 + /// + public enum MenuEnumType + { + /// + /// 菜单 + /// + Menu, + /// + /// 权限 + /// + Permission + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantConsts.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantConsts.cs new file mode 100644 index 0000000..2617a42 --- /dev/null +++ b/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; + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantInfoDto.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuGrantInfoDto.cs new file mode 100644 index 0000000..dde6f56 --- /dev/null +++ b/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 + { + /// + /// Id + /// + 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 GrantedProviders { get; set; } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuManagementDomainSharedModule.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuManagementDomainSharedModule.cs new file mode 100644 index 0000000..361acf1 --- /dev/null +++ b/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(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes(typeof(AbpValidationResource)) + .AddVirtualJson("/Sanhe/Abp/MenuManagement/Localization/Resources"); + }); + + Configure(options => + { + options.MapCodeNamespace("MenuManagement", typeof(MenuManagementResource)); + }); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuProviderInfo.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain.Shared/Sanhe/Abp/MenuManagement/MenuProviderInfo.cs new file mode 100644 index 0000000..cd175fe --- /dev/null +++ b/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; + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/FodyWeavers.xml b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/FodyWeavers.xml new file mode 100644 index 0000000..1715698 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe.Abp.MenuManagement.Domain.csproj b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe.Abp.MenuManagement.Domain.csproj new file mode 100644 index 0000000..60e66ab --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe.Abp.MenuManagement.Domain.csproj @@ -0,0 +1,20 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantChecker.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantChecker.cs new file mode 100644 index 0000000..5aada56 --- /dev/null +++ b/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 CheckAsync(Guid menuId, string providerName, string providerKey); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRepository.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRepository.cs new file mode 100644 index 0000000..4473cd5 --- /dev/null +++ b/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 + { + Task FindAsync(Guid menuId, + string providerName, + string providerKey, + CancellationToken cancellationToken = default); + + Task> GetListAsync( + string providerName, + string providerKey, + CancellationToken cancellationToken = default + ); + + Task> GetGrantByMenuIdAsync(Guid menuId, bool noTracking = true); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRuntimeCheckerProvider.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuGrantRuntimeCheckerProvider.cs new file mode 100644 index 0000000..52cc7f2 --- /dev/null +++ b/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 CheckAsync(MenuGrantRuntimeCheckerContent context); + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManagementProvider.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManagementProvider.cs new file mode 100644 index 0000000..4fc2a3d --- /dev/null +++ b/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 CheckAsync( + [NotNull] Guid menuId, + [NotNull] string providerName, + [NotNull] string providerKey + ); + + Task SetAsync( + [NotNull] Guid menuId, + [NotNull] string providerKey, + bool isGranted + ); + } + +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManager.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuManager.cs new file mode 100644 index 0000000..51b1d71 --- /dev/null +++ b/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 GetPermissions(string providerName); + Task 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); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuRepository.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IMenuRepository.cs new file mode 100644 index 0000000..e43264a --- /dev/null +++ b/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 + { + + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IUserMenuGrantChecker.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/IUserMenuGrantChecker.cs new file mode 100644 index 0000000..3e0e1ec --- /dev/null +++ b/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 CheckAsync(ClaimsPrincipal claimsPrincipal, Menu menu); + } + + public class UserMenuGrantChecker : IUserMenuGrantChecker, ITransientDependency + { + private readonly ICurrentTenant _currentTenant; + private readonly IEnumerable _checkerProviders; + + public UserMenuGrantChecker( + ICurrentTenant currentTenant, + IEnumerable checkerProviders + ) + { + _currentTenant = currentTenant; + _checkerProviders = checkerProviders; + } + + public async Task 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; + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Menu.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Menu.cs new file mode 100644 index 0000000..7f8b0b4 --- /dev/null +++ b/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 +{ + /// + /// 菜单 + /// + [DisplayName("菜单")] + public class Menu : FullAuditedAggregateRoot + { + /// + /// 名称 + /// + [DisplayName("名称")] + public virtual string Name { get; protected set; } + /// + /// 显示名称 + /// + [DisplayName("显示名称")] + public virtual string DisplayName { get; protected set; } + /// + /// 类型 + /// + [DisplayName("类型")] + public virtual MenuEnumType MenuType { get; protected set; } + /// + /// 组件路径 + /// + [DisplayName("组件路径")] + public virtual string ComponentPath { get; set; } + /// + /// 路由路径 + /// + [DisplayName("路由路径")] + public virtual string RouterPath { get; set; } + /// + /// 父Id + /// + [DisplayName("父Id")] + public virtual Guid? ParentId { get; set; } + /// + /// 图标 + /// + [DisplayName("图标")] + public virtual string Icon { get; set; } + /// + /// 排序 + /// + [DisplayName("排序")] + public virtual string Sort { get; set; } + /// + /// window.open _blank + /// + [DisplayName("window.open _blank ")] + public virtual string TargetUrl { get; set; } + /// + /// 此菜单关联的权限key + /// + [DisplayName("此菜单关联的权限key")] + public virtual string PermissionKey { get; set; } + /// + /// 表示多租户应用程序中的所属方 + /// + [DisplayName("表示多租户应用程序中的所属方")] + public virtual MultiTenancySides MultiTenancySide { get; set; } + /// + /// 父菜单 + /// + public virtual Menu Parent { get; set; } + /// + /// 子菜单 + /// + public virtual Collection 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(); + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrant.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrant.cs new file mode 100644 index 0000000..7ebc468 --- /dev/null +++ b/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 +{ + /// + /// 菜单分配 + /// + [DisplayName("菜单分配")] + public class MenuGrant : Entity, IMultiTenant + { + /// + /// 租户Id + /// + [DisplayName("租户Id")] + public virtual Guid? TenantId { get; protected set; } + /// + /// 菜单Id + /// + [DisplayName("菜单Id")] + [NotNull] + public virtual Guid MenuId { get; protected set; } + /// + /// 提供器名称 + /// + [DisplayName("提供器名称")] + [NotNull] + public virtual string ProviderName { get; protected set; } + /// + /// 提供器Key + /// + [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; + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItem.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItem.cs new file mode 100644 index 0000000..e1c113e --- /dev/null +++ b/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; + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItemInvalidator.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantCacheItemInvalidator.cs new file mode 100644 index 0000000..f74ac99 --- /dev/null +++ b/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>, + ILocalEventHandler>, + ITransientDependency + { + public MenuGrantCacheItemInvalidator( + ICurrentTenant currentTenant, + IDistributedCache cache + ) + { + CurrentTenant = currentTenant; + Cache = cache; + } + + protected ICurrentTenant CurrentTenant { get; } + + protected IDistributedCache Cache { get; } + + public async Task HandleEventAsync(EntityCreatedEventData 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 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); + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantChecker.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantChecker.cs new file mode 100644 index 0000000..6e9ab69 --- /dev/null +++ b/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 _cache; + private readonly ILogger _logger; + private readonly IMenuGrantRepository _menuGrantRepository; + + public MenuGrantChecker( + IDistributedCache cache, + ILogger logger, + IMenuGrantRepository menuGrantRepository + ) + { + _cache = cache; + _logger = logger; + _menuGrantRepository = menuGrantRepository; + } + + public async Task 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; + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantInfo.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantInfo.cs new file mode 100644 index 0000000..53aa80f --- /dev/null +++ b/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; + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantResultEnum.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantResultEnum.cs new file mode 100644 index 0000000..5c76819 --- /dev/null +++ b/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 + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerContent.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerContent.cs new file mode 100644 index 0000000..a7eb44a --- /dev/null +++ b/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; } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerProvider.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuGrantRuntimeCheckerProvider.cs new file mode 100644 index 0000000..ea5d8ad --- /dev/null +++ b/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 CheckAsync(MenuGrantRuntimeCheckerContent context); + } + + public class RoleMenuGrantRuntimeCheckerProvider : MenuGrantRuntimeCheckerProvider, ITransientDependency + { + public RoleMenuGrantRuntimeCheckerProvider(IMenuGrantChecker menuGrantChecker) : base(menuGrantChecker) + { + } + + public override async Task 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 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; + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDbProperties.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDbProperties.cs new file mode 100644 index 0000000..12b09ef --- /dev/null +++ b/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"; +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDomainModule.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementDomainModule.cs new file mode 100644 index 0000000..1406016 --- /dev/null +++ b/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 +{ + +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementOptions.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementOptions.cs new file mode 100644 index 0000000..1df0a80 --- /dev/null +++ b/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 ManagementProviders { get; } + + public MenuManagementOptions() + { + ManagementProviders = new TypeList(); + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementProvider.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManagementProvider.cs new file mode 100644 index 0000000..32f1330 --- /dev/null +++ b/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 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); + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManager.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuManager.cs new file mode 100644 index 0000000..4e969a6 --- /dev/null +++ b/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 _managementProviders; + private readonly MenuManagementOptions _options; + + public MenuManager( + IPermissionDefinitionManager permissionDefinitionManager, + IMenuGrantRepository menuGrantRepository, + IPermissionManager permissionManager, + IOptions 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 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 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); + } + } + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuWithGrantedProviders.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/MenuWithGrantedProviders.cs new file mode 100644 index 0000000..7a5a73d --- /dev/null +++ b/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 Providers { get; set; } + + public MenuWithGrantedProviders([NotNull] Guid menuId, bool isGranted) + { + Check.NotNull(menuId, nameof(menuId)); + + MenuId = menuId; + IsGranted = isGranted; + + Providers = new List(); + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Permission.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Permission.cs new file mode 100644 index 0000000..74103ee --- /dev/null +++ b/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, 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 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(); + } + + 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; + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/PermissionGroup.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/PermissionGroup.cs new file mode 100644 index 0000000..c4b0699 --- /dev/null +++ b/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, 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 Children { get; set; } + public virtual Collection 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(); + Permissions = new Collection(); + } + + 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; + } + } +} \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettingDefinitionProvider.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettingDefinitionProvider.cs new file mode 100644 index 0000000..bd9f8d4 --- /dev/null +++ b/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. + */ + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettings.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.Domain/Sanhe/Abp/MenuManagement/Settings/MenuManagementSettings.cs new file mode 100644 index 0000000..94ee616 --- /dev/null +++ b/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"; + */ +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/FodyWeavers.xml b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 0000000..1715698 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe.Abp.MenuManagement.EntityFrameworkCore.csproj b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe.Abp.MenuManagement.EntityFrameworkCore.csproj new file mode 100644 index 0000000..30e9975 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe.Abp.MenuManagement.EntityFrameworkCore.csproj @@ -0,0 +1,20 @@ + + + + + + + net6.0 + + + + + + + + + + + + + diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/IMenuManagementDbContext.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/IMenuManagementDbContext.cs new file mode 100644 index 0000000..466b788 --- /dev/null +++ b/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 Menus { get; set; } + DbSet MenuGrants { get; set; } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContext.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContext.cs new file mode 100644 index 0000000..e40e185 --- /dev/null +++ b/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, IMenuManagementDbContext +{ + public DbSet Menus { get; set; } + public DbSet MenuGrants { get; set; } + + public MenuManagementDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + builder.ConfigureMenuManagement(); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContextModelCreatingExtensions.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementDbContextModelCreatingExtensions.cs new file mode 100644 index 0000000..fff0676 --- /dev/null +++ b/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(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(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 }); + }); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementEntityFrameworkCoreModule.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/EntityFrameworkCore/MenuManagementEntityFrameworkCoreModule.cs new file mode 100644 index 0000000..c9fbf37 --- /dev/null +++ b/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(options => + { + options.AddRepository(); + }); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuGrantRepository.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuGrantRepository.cs new file mode 100644 index 0000000..e7b1c5e --- /dev/null +++ b/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, IMenuGrantRepository + { + public MenuGrantRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + + } + + public virtual async Task 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> 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() 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> GetGrantByMenuIdAsync(Guid menuId, bool noTracking = true) + { + var query = (await GetDbSetAsync()).Where(x => x.MenuId == menuId); + + if (noTracking) + { + query = query.AsNoTracking(); + } + + return await query.ToListAsync(); + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuRepository.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.EntityFrameworkCore/Sanhe/Abp/MenuManagement/MenuRepository.cs new file mode 100644 index 0000000..ef591a3 --- /dev/null +++ b/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, IMenuRepository + { + public MenuRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + + } + + public override async Task> WithDetailsAsync() + { + var queryable = await GetQueryableAsync(); + + return queryable.Include(x => x.Parent); + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/FodyWeavers.xml b/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/FodyWeavers.xml new file mode 100644 index 0000000..1715698 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe.Abp.MenuManagement.HttpApi.csproj b/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe.Abp.MenuManagement.HttpApi.csproj new file mode 100644 index 0000000..e1a0116 --- /dev/null +++ b/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe.Abp.MenuManagement.HttpApi.csproj @@ -0,0 +1,16 @@ + + + + + + + net6.0 + + + + + + + + + diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuController.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuController.cs new file mode 100644 index 0000000..cb4942e --- /dev/null +++ b/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 GetAsync(Guid id) + { + return _menuAppService.GetAsync(id); + } + + [HttpGet] + public virtual Task> GetListAsync(MenuRequestDto input) + { + return _menuAppService.GetListAsync(input); + } + + [HttpPost] + public virtual Task CreateAsync(CreateOrUpdateMenuDto input) + { + return _menuAppService.CreateAsync(input); + } + + [HttpPut("{id}")] + public virtual Task 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> GetAuthPolicies() + { + return _menuAppService.GetAuthPolicies(); + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuGrantController.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuGrantController.cs new file mode 100644 index 0000000..8733466 --- /dev/null +++ b/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 +{ + /// + /// 菜单分配 + /// + [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 GetListAsync() + { + return _menuGrantAppService.GetListAsync(); + } + + [HttpGet] + public virtual Task 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); + } + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementController.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementController.cs new file mode 100644 index 0000000..7590883 --- /dev/null +++ b/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); + } +} diff --git a/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementHttpApiModule.cs b/modules/menu-management/Sanhe.Abp.MenuManagement.HttpApi/Sanhe/Abp/MenuManagement/MenuManagementHttpApiModule.cs new file mode 100644 index 0000000..ce514a0 --- /dev/null +++ b/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(mvcBuilder => + { + mvcBuilder.AddApplicationPartIfNotExists(typeof(MenuManagementHttpApiModule).Assembly); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes(typeof(AbpUiResource)); + }); + } +}