From 8c1444d67ed6d3f9f0a5b5bcf4d7811a1b7e433f Mon Sep 17 00:00:00 2001
From: cKey <35512826+colinin@users.noreply.github.com>
Date: Sun, 27 Sep 2020 11:58:36 +0800
Subject: [PATCH] add functional management for the client
---
aspnet-core/LINGYUN.MicroService.sln | 19 +++++++++-
...INGYUN.Abp.FeatureManagement.Client.csproj | 24 +++++++++++++
.../AbpFeatureManagementClientModule.cs | 25 +++++++++++++
.../Client/ClientFeatureManagementProvider.cs | 33 +++++++++++++++++
...ientFeaturePermissionDefinitionProvider.cs | 33 +++++++++++++++++
.../ClientFeaturePermissionNames.cs | 16 +++++++++
.../ClientFeatureManagerExtensions.cs | 36 +++++++++++++++++++
.../Localization/Client/en.json | 7 ++++
.../Localization/Client/zh-Hans.json | 7 ++++
.../LINGYUN.Abp.Features.Client.csproj | 14 ++++++++
.../Client/AbpFeaturesClientModule.cs | 18 ++++++++++
.../Client/ClientFeatureValueProvider.cs | 33 +++++++++++++++++
...ntityServerPermissionDefinitionProvider.cs | 12 ++++++-
13 files changed, 275 insertions(+), 2 deletions(-)
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN.Abp.FeatureManagement.Client.csproj
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/AbpFeatureManagementClientModule.cs
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/ClientFeatureManagementProvider.cs
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionDefinitionProvider.cs
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionNames.cs
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/ClientFeatureManagerExtensions.cs
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/en.json
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/zh-Hans.json
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN.Abp.Features.Client.csproj
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN/Abp/Features/Client/AbpFeaturesClientModule.cs
create mode 100644 aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN/Abp/Features/Client/ClientFeatureValueProvider.cs
diff --git a/aspnet-core/LINGYUN.MicroService.sln b/aspnet-core/LINGYUN.MicroService.sln
index b907ce0f3..dd7b8e2b1 100644
--- a/aspnet-core/LINGYUN.MicroService.sln
+++ b/aspnet-core/LINGYUN.MicroService.sln
@@ -223,7 +223,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.Valida
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.Validation.Redis.Tests", "tests\LINGYUN.Abp.Features.Validation.Redis.Tests\LINGYUN.Abp.Features.Validation.Redis.Tests.csproj", "{F12F4645-C0FE-4129-8C71-65B4039DC445}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Features.Validation.Tests", "tests\LINGYUN.Abp.Features.Validation.Tests\LINGYUN.Abp.Features.Validation.Tests.csproj", "{C457FA70-8732-44B8-A018-C96D14025D4B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.Validation.Tests", "tests\LINGYUN.Abp.Features.Validation.Tests\LINGYUN.Abp.Features.Validation.Tests.csproj", "{C457FA70-8732-44B8-A018-C96D14025D4B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "features", "features", "{08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.FeatureManagement.Client", "modules\features\LINGYUN.Abp.FeatureManagement.Client\LINGYUN.Abp.FeatureManagement.Client.csproj", "{7071E78B-755B-410A-830B-AA05D7168944}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Features.Client", "modules\features\LINGYUN.Abp.Features.Client\LINGYUN.Abp.Features.Client.csproj", "{87B65CBD-0FF4-4FB5-9ABC-161911A71179}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -599,6 +605,14 @@ Global
{C457FA70-8732-44B8-A018-C96D14025D4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C457FA70-8732-44B8-A018-C96D14025D4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C457FA70-8732-44B8-A018-C96D14025D4B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7071E78B-755B-410A-830B-AA05D7168944}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7071E78B-755B-410A-830B-AA05D7168944}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7071E78B-755B-410A-830B-AA05D7168944}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7071E78B-755B-410A-830B-AA05D7168944}.Release|Any CPU.Build.0 = Release|Any CPU
+ {87B65CBD-0FF4-4FB5-9ABC-161911A71179}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {87B65CBD-0FF4-4FB5-9ABC-161911A71179}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {87B65CBD-0FF4-4FB5-9ABC-161911A71179}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {87B65CBD-0FF4-4FB5-9ABC-161911A71179}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -712,6 +726,9 @@ Global
{D3E65610-4167-4235-9C9D-1E1FAD4C0CE6} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E}
{F12F4645-C0FE-4129-8C71-65B4039DC445} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}
{C457FA70-8732-44B8-A018-C96D14025D4B} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}
+ {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8} = {C5CAD011-DF84-4914-939C-0C029DCEF26F}
+ {7071E78B-755B-410A-830B-AA05D7168944} = {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8}
+ {87B65CBD-0FF4-4FB5-9ABC-161911A71179} = {08BD73E6-72CE-4A8A-896D-2DFFF4D7D2F8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN.Abp.FeatureManagement.Client.csproj b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN.Abp.FeatureManagement.Client.csproj
new file mode 100644
index 000000000..7b8ebf8ed
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN.Abp.FeatureManagement.Client.csproj
@@ -0,0 +1,24 @@
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/AbpFeatureManagementClientModule.cs b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/AbpFeatureManagementClientModule.cs
new file mode 100644
index 000000000..c6c00aa47
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/AbpFeatureManagementClientModule.cs
@@ -0,0 +1,25 @@
+using LINGYUN.Abp.FeatureManagement.Client;
+using LINGYUN.Abp.FeatureManagement.Client.Permissions;
+using LINGYUN.Abp.Features.Client;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.FeatureManagement
+{
+ [DependsOn(
+ typeof(AbpFeaturesClientModule),
+ typeof(AbpFeatureManagementDomainModule)
+ )]
+ public class AbpFeatureManagementClientModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.Providers.Add();
+
+ options.ProviderPolicies[ClientFeatureValueProvider.ProviderName] = ClientFeaturePermissionNames.Clients.ManageFeatures;
+ });
+ }
+ }
+}
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/ClientFeatureManagementProvider.cs b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/ClientFeatureManagementProvider.cs
new file mode 100644
index 000000000..477b41cbe
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/ClientFeatureManagementProvider.cs
@@ -0,0 +1,33 @@
+using LINGYUN.Abp.Features.Client;
+using Volo.Abp.Clients;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.FeatureManagement;
+
+namespace LINGYUN.Abp.FeatureManagement.Client
+{
+
+ public class ClientFeatureManagementProvider : FeatureManagementProvider, ITransientDependency
+ {
+ public override string Name => ClientFeatureValueProvider.ProviderName;
+
+ protected ICurrentClient CurrentClient;
+
+ public ClientFeatureManagementProvider(
+ ICurrentClient currentClient,
+ IFeatureManagementStore store)
+ : base(store)
+ {
+ CurrentClient = currentClient;
+ }
+
+ protected override string NormalizeProviderKey(string providerKey)
+ {
+ if (providerKey != null)
+ {
+ return providerKey;
+ }
+
+ return CurrentClient.Id;
+ }
+ }
+}
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionDefinitionProvider.cs b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionDefinitionProvider.cs
new file mode 100644
index 000000000..495f23b40
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionDefinitionProvider.cs
@@ -0,0 +1,33 @@
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.FeatureManagement.Localization;
+using Volo.Abp.Localization;
+
+namespace LINGYUN.Abp.FeatureManagement.Client.Permissions
+{
+ public class ClientFeaturePermissionDefinitionProvider : PermissionDefinitionProvider
+ {
+ public override void Define(IPermissionDefinitionContext context)
+ {
+ var identityServerGroup = context.GetGroupOrNull(ClientFeaturePermissionNames.GroupName);
+ if (identityServerGroup == null)
+ {
+ identityServerGroup = context
+ .AddGroup(
+ name: ClientFeaturePermissionNames.GroupName,
+ displayName: L("Permissions:IdentityServer"),
+ multiTenancySide: Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ }
+ identityServerGroup
+ .AddPermission(
+ name: ClientFeaturePermissionNames.Clients.ManageFeatures,
+ displayName: L("Permissions:ManageFeatures"),
+ multiTenancySide: Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .WithProviders(ClientPermissionValueProvider.ProviderName);
+ }
+
+ protected virtual LocalizableString L(string name)
+ {
+ return LocalizableString.Create(name);
+ }
+ }
+}
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionNames.cs b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionNames.cs
new file mode 100644
index 000000000..d0b1a7b7e
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionNames.cs
@@ -0,0 +1,16 @@
+namespace LINGYUN.Abp.FeatureManagement.Client.Permissions
+{
+ public class ClientFeaturePermissionNames
+ {
+ public const string GroupName = "IdentityServer";
+
+ public static class Clients
+ {
+ public const string Default = GroupName + ".Clients";
+ ///
+ /// 管理功能权限
+ ///
+ public const string ManageFeatures = Default + ".ManageFeatures";
+ }
+ }
+}
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/ClientFeatureManagerExtensions.cs b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/ClientFeatureManagerExtensions.cs
new file mode 100644
index 000000000..60f929f79
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/ClientFeatureManagerExtensions.cs
@@ -0,0 +1,36 @@
+using JetBrains.Annotations;
+using LINGYUN.Abp.Features.Client;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.FeatureManagement;
+
+namespace LINGYUN.Abp.FeatureManagement
+{
+ public static class ClientFeatureManagerExtensions
+ {
+ public static Task GetOrNullForClientAsync(this IFeatureManager featureManager, [NotNull] string name, string clientId, bool fallback = true)
+ {
+ return featureManager.GetOrNullAsync(name, ClientFeatureValueProvider.ProviderName, clientId, fallback);
+ }
+
+ public static Task> GetAllForClientAsync(this IFeatureManager featureManager, string clientId, bool fallback = true)
+ {
+ return featureManager.GetAllAsync(ClientFeatureValueProvider.ProviderName, clientId, fallback);
+ }
+
+ public static Task GetOrNullWithProviderForClientAsync(this IFeatureManager featureManager, [NotNull] string name, string clientId, bool fallback = true)
+ {
+ return featureManager.GetOrNullWithProviderAsync(name, ClientFeatureValueProvider.ProviderName, clientId, fallback);
+ }
+
+ public static Task> GetAllWithProviderForClientAsync(this IFeatureManager featureManager, string clientId, bool fallback = true)
+ {
+ return featureManager.GetAllWithProviderAsync(ClientFeatureValueProvider.ProviderName, clientId, fallback);
+ }
+
+ public static Task SetForEditionAsync(this IFeatureManager featureManager, string clientId, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false)
+ {
+ return featureManager.SetAsync(name, value, ClientFeatureValueProvider.ProviderName, clientId, forceToSet);
+ }
+ }
+}
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/en.json b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/en.json
new file mode 100644
index 000000000..8c72ee646
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/en.json
@@ -0,0 +1,7 @@
+{
+ "culture": "en",
+ "texts": {
+ "Permissions:IdentityServer": "IdentityServer",
+ "Permissions:ManageFeatures": "Manage features"
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/zh-Hans.json b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/zh-Hans.json
new file mode 100644
index 000000000..7f7181c99
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/zh-Hans.json
@@ -0,0 +1,7 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+ "Permissions:IdentityServer": "IdentityServer管理",
+ "ManageFeatures": "管理功能"
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN.Abp.Features.Client.csproj b/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN.Abp.Features.Client.csproj
new file mode 100644
index 000000000..69acd1542
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN.Abp.Features.Client.csproj
@@ -0,0 +1,14 @@
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN/Abp/Features/Client/AbpFeaturesClientModule.cs b/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN/Abp/Features/Client/AbpFeaturesClientModule.cs
new file mode 100644
index 000000000..6b5b6475f
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN/Abp/Features/Client/AbpFeaturesClientModule.cs
@@ -0,0 +1,18 @@
+using Volo.Abp.Features;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.Features.Client
+{
+ [DependsOn(
+ typeof(AbpFeaturesModule))]
+ public class AbpFeaturesClientModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.ValueProviders.Add();
+ });
+ }
+ }
+}
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN/Abp/Features/Client/ClientFeatureValueProvider.cs b/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN/Abp/Features/Client/ClientFeatureValueProvider.cs
new file mode 100644
index 000000000..14ac3ea22
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.Features.Client/LINGYUN/Abp/Features/Client/ClientFeatureValueProvider.cs
@@ -0,0 +1,33 @@
+using System.Threading.Tasks;
+using Volo.Abp.Clients;
+using Volo.Abp.Features;
+
+namespace LINGYUN.Abp.Features.Client
+{
+ public class ClientFeatureValueProvider : FeatureValueProvider
+ {
+ public const string ProviderName = "C";
+
+ public override string Name => ProviderName;
+
+ protected ICurrentClient CurrentClient;
+
+ public ClientFeatureValueProvider(
+ IFeatureStore featureStore,
+ ICurrentClient currentClient)
+ : base(featureStore)
+ {
+ CurrentClient = currentClient;
+ }
+
+ public override async Task GetOrNullAsync(FeatureDefinition feature)
+ {
+ if (!CurrentClient.IsAuthenticated)
+ {
+ return null;
+ }
+
+ return await FeatureStore.GetOrNullAsync(feature.Name, Name, CurrentClient.Id);
+ }
+ }
+}
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs
index 1a95296ad..6b19a03e1 100644
--- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs
@@ -11,8 +11,18 @@ namespace LINGYUN.Abp.IdentityServer
{
// TODO: 身份认证服务器应该只能主机管辖
// 增加 MultiTenancySides.Host
- var identityServerGroup = context.AddGroup(AbpIdentityServerPermissions.GroupName, L("Permissions:IdentityServer"), MultiTenancySides.Host);
+ // var identityServerGroup = context.AddGroup(AbpIdentityServerPermissions.GroupName, L("Permissions:IdentityServer"), MultiTenancySides.Host);
+ // 与 LINGYUN.Abp.FeatureManagement.Client 模块搭配,这样干可以不依赖于模块优先级
+ var identityServerGroup = context.GetGroupOrNull(AbpIdentityServerPermissions.GroupName);
+ if (identityServerGroup == null)
+ {
+ identityServerGroup = context
+ .AddGroup(
+ name: AbpIdentityServerPermissions.GroupName,
+ displayName: L("Permissions:IdentityServer"),
+ multiTenancySide: MultiTenancySides.Host);
+ }
// 客户端权限
var clientPermissions = identityServerGroup.AddPermission(AbpIdentityServerPermissions.Clients.Default, L("Permissions:Clients"), MultiTenancySides.Host);
clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Create, L("Permissions:Create"), MultiTenancySides.Host);