diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln
index ec5581643..86ec35372 100644
--- a/aspnet-core/LINGYUN.MicroService.All.sln
+++ b/aspnet-core/LINGYUN.MicroService.All.sln
@@ -284,6 +284,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.F
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.SettingManagement", "modules\oss-management\LINGYUN.Abp.OssManagement.SettingManagement\LINGYUN.Abp.OssManagement.SettingManagement.csproj", "{BD74BE00-54E4-4979-8797-E8027695F396}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Features.LimitValidation.Redis.Client", "modules\common\LINGYUN.Abp.Features.LimitValidation.Redis.Client\LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj", "{48DE251A-3482-4934-BC26-F99D2235AC9F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -746,6 +748,10 @@ Global
{BD74BE00-54E4-4979-8797-E8027695F396}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD74BE00-54E4-4979-8797-E8027695F396}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD74BE00-54E4-4979-8797-E8027695F396}.Release|Any CPU.Build.0 = Release|Any CPU
+ {48DE251A-3482-4934-BC26-F99D2235AC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {48DE251A-3482-4934-BC26-F99D2235AC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {48DE251A-3482-4934-BC26-F99D2235AC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {48DE251A-3482-4934-BC26-F99D2235AC9F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -887,6 +893,7 @@ Global
{D5036D3F-1C53-47EE-BA50-AD290AE062D7} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6}
{3E5EBCEC-78C9-4A1A-BF04-A216AA6A921F} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6}
{BD74BE00-54E4-4979-8797-E8027695F396} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6}
+ {48DE251A-3482-4934-BC26-F99D2235AC9F} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
index cca96b655..7b5589b2f 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
+++ b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
@@ -183,6 +183,65 @@
+
+
+ CAP消息扩展
+
+
+
+
+ 尝试获取消息标头中的租户标识
+
+
+
+
+
+
+
+ 获取消息标头中的租户标识
+
+
+
+
+
+
+ 重写 ISubscribeInvoker 实现 Abp 租户集成
+
+
+
+
+ AbpCAPSubscribeInvoker
+
+
+
+
+
+
+
+
+ 调用订阅者方法
+
+
+
+
+
+
+
+ 获取事件处理类实例
+
+
+
+
+
+
+
+ 通过给定的类型实例与参数调用订阅者方法
+
+
+
+
+
+
CAP分布式事件总线
@@ -213,14 +272,32 @@
本地事件集合
-
+
+
+ 当前用户
+
+
+
+
+ 当前客户端
+
+
+
+
+ 取消令牌
+
+
+
constructor
+
+
+
@@ -300,6 +377,62 @@
+
+
+ Executes the configured method on . This can be used whether or not
+ the configured method is asynchronous.
+
+
+ Even if the target method is asynchronous, it's desirable to invoke it using Execute rather than
+ ExecuteAsync if you know at compile time what the return type is, because then you can directly
+ "await" that value (via a cast), and then the generated code will be able to reference the
+ resulting awaitable as a value-typed variable. If you use ExecuteAsync instead, the generated
+ code will have to treat the resulting awaitable as a boxed object, because it doesn't know at
+ compile time what type it would be.
+
+ The object whose method is to be executed.
+ Parameters to pass to the method.
+ The method return value.
+
+
+
+ Executes the configured method on . This can only be used if the configured
+ method is asynchronous.
+
+
+ If you don't know at compile time the type of the method's returned awaitable, you can use ExecuteAsync,
+ which supplies an awaitable-of-object. This always works, but can incur several extra heap allocations
+ as compared with using Execute and then using "await" on the result value typecasted to the known
+ awaitable type. The possible extra heap allocations are for:
+ 1. The custom awaitable (though usually there's a heap allocation for this anyway, since normally
+ it's a reference type, and you normally create a new instance per call).
+ 2. The custom awaiter (whether or not it's a value type, since if it's not, you need a new instance
+ of it, and if it is, it will have to be boxed so the calling code can reference it as an object).
+ 3. The async result value, if it's a value type (it has to be boxed as an object, since the calling
+ code doesn't know what type it's going to be).
+
+ The object whose method is to be executed.
+ Parameters to pass to the method.
+ An object that you can "await" to get the method return value.
+
+
+
+ Provides a common awaitable structure that can
+ return, regardless of whether the underlying value is a System.Task, an FSharpAsync, or an
+ application-defined custom awaitable.
+
+
+
+
+ Helper for detecting whether a given type is FSharpAsync`1, and if so, supplying
+ an for mapping instances of that type to a C# awaitable.
+
+
+ The main design goal here is to avoid taking a compile-time dependency on
+ FSharp.Core.dll, because non-F# applications wouldn't use it. So all the references
+ to FSharp types have to be constructed dynamically at runtime.
+
+
CAP ServiceCollectionExtensions
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
index cca96b655..7b5589b2f 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
+++ b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
@@ -183,6 +183,65 @@
+
+
+ CAP消息扩展
+
+
+
+
+ 尝试获取消息标头中的租户标识
+
+
+
+
+
+
+
+ 获取消息标头中的租户标识
+
+
+
+
+
+
+ 重写 ISubscribeInvoker 实现 Abp 租户集成
+
+
+
+
+ AbpCAPSubscribeInvoker
+
+
+
+
+
+
+
+
+ 调用订阅者方法
+
+
+
+
+
+
+
+ 获取事件处理类实例
+
+
+
+
+
+
+
+ 通过给定的类型实例与参数调用订阅者方法
+
+
+
+
+
+
CAP分布式事件总线
@@ -213,14 +272,32 @@
本地事件集合
-
+
+
+ 当前用户
+
+
+
+
+ 当前客户端
+
+
+
+
+ 取消令牌
+
+
+
constructor
+
+
+
@@ -300,6 +377,62 @@
+
+
+ Executes the configured method on . This can be used whether or not
+ the configured method is asynchronous.
+
+
+ Even if the target method is asynchronous, it's desirable to invoke it using Execute rather than
+ ExecuteAsync if you know at compile time what the return type is, because then you can directly
+ "await" that value (via a cast), and then the generated code will be able to reference the
+ resulting awaitable as a value-typed variable. If you use ExecuteAsync instead, the generated
+ code will have to treat the resulting awaitable as a boxed object, because it doesn't know at
+ compile time what type it would be.
+
+ The object whose method is to be executed.
+ Parameters to pass to the method.
+ The method return value.
+
+
+
+ Executes the configured method on . This can only be used if the configured
+ method is asynchronous.
+
+
+ If you don't know at compile time the type of the method's returned awaitable, you can use ExecuteAsync,
+ which supplies an awaitable-of-object. This always works, but can incur several extra heap allocations
+ as compared with using Execute and then using "await" on the result value typecasted to the known
+ awaitable type. The possible extra heap allocations are for:
+ 1. The custom awaitable (though usually there's a heap allocation for this anyway, since normally
+ it's a reference type, and you normally create a new instance per call).
+ 2. The custom awaiter (whether or not it's a value type, since if it's not, you need a new instance
+ of it, and if it is, it will have to be boxed so the calling code can reference it as an object).
+ 3. The async result value, if it's a value type (it has to be boxed as an object, since the calling
+ code doesn't know what type it's going to be).
+
+ The object whose method is to be executed.
+ Parameters to pass to the method.
+ An object that you can "await" to get the method return value.
+
+
+
+ Provides a common awaitable structure that can
+ return, regardless of whether the underlying value is a System.Task, an FSharpAsync, or an
+ application-defined custom awaitable.
+
+
+
+
+ Helper for detecting whether a given type is FSharpAsync`1, and if so, supplying
+ an for mapping instances of that type to a C# awaitable.
+
+
+ The main design goal here is to avoid taking a compile-time dependency on
+ FSharp.Core.dll, because non-F# applications wouldn't use it. So all the references
+ to FSharp types have to be constructed dynamically at runtime.
+
+
CAP ServiceCollectionExtensions
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj
new file mode 100644
index 000000000..43a22ac96
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj
@@ -0,0 +1,15 @@
+
+
+
+
+
+ netstandard2.0
+
+ 功能限制验证组件Redis客户端格式实现
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN/Abp/Features/LimitValidation/Redis/Client/AbpFeaturesValidationRedisClientModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN/Abp/Features/LimitValidation/Redis/Client/AbpFeaturesValidationRedisClientModule.cs
new file mode 100644
index 000000000..2606d3789
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN/Abp/Features/LimitValidation/Redis/Client/AbpFeaturesValidationRedisClientModule.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.Features.LimitValidation.Redis.Client
+{
+ [DependsOn(typeof(AbpFeaturesValidationRedisModule))]
+ public class AbpFeaturesValidationRedisClientModule : AbpModule
+ {
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN/Abp/Features/LimitValidation/Redis/Client/RedisClientLimitFeatureNamingNormalizer.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN/Abp/Features/LimitValidation/Redis/Client/RedisClientLimitFeatureNamingNormalizer.cs
new file mode 100644
index 000000000..8269af29f
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN/Abp/Features/LimitValidation/Redis/Client/RedisClientLimitFeatureNamingNormalizer.cs
@@ -0,0 +1,33 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Clients;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.Features.LimitValidation.Redis.Client
+{
+ [Dependency(ServiceLifetime.Singleton, ReplaceServices = true)]
+ [ExposeServices(
+ typeof(IRedisLimitFeatureNamingNormalizer),
+ typeof(RedisLimitFeatureNamingNormalizer))]
+ public class RedisClientLimitFeatureNamingNormalizer : RedisLimitFeatureNamingNormalizer
+ {
+ protected ICurrentClient CurrentClient { get; }
+ public RedisClientLimitFeatureNamingNormalizer(
+ ICurrentClient currentClient,
+ ICurrentTenant currentTenant) : base(currentTenant)
+ {
+ CurrentClient = currentClient;
+ }
+
+ public override string NormalizeFeatureName(string instance, RequiresLimitFeatureContext context)
+ {
+ if (CurrentClient.IsAuthenticated)
+ {
+ return CurrentTenant.IsAvailable
+ ? $"{instance}t:RequiresLimitFeature;t:{CurrentTenant.Id};c:{CurrentClient.Id};f:{context.LimitFeature}"
+ : $"{instance}tc:RequiresLimitFeature;c:{CurrentClient.Id};f:{context.LimitFeature}";
+ }
+ return base.NormalizeFeatureName(instance, context);
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/IRedisLimitFeatureNamingNormalizer.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/IRedisLimitFeatureNamingNormalizer.cs
new file mode 100644
index 000000000..6b380782f
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/IRedisLimitFeatureNamingNormalizer.cs
@@ -0,0 +1,7 @@
+namespace LINGYUN.Abp.Features.LimitValidation.Redis
+{
+ public interface IRedisLimitFeatureNamingNormalizer
+ {
+ string NormalizeFeatureName(string instance, RequiresLimitFeatureContext context);
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisLimitFeatureNamingNormalizer.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisLimitFeatureNamingNormalizer.cs
new file mode 100644
index 000000000..6766cee2c
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisLimitFeatureNamingNormalizer.cs
@@ -0,0 +1,25 @@
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.Features.LimitValidation.Redis
+{
+ public class RedisLimitFeatureNamingNormalizer : IRedisLimitFeatureNamingNormalizer, ISingletonDependency
+ {
+ protected ICurrentTenant CurrentTenant { get; }
+
+ public RedisLimitFeatureNamingNormalizer(
+ ICurrentTenant currentTenant)
+ {
+ CurrentTenant = currentTenant;
+ }
+
+ public virtual string NormalizeFeatureName(string instance, RequiresLimitFeatureContext context)
+ {
+ if (CurrentTenant.IsAvailable)
+ {
+ return $"{instance}t:RequiresLimitFeature;t:{CurrentTenant.Id};f:{context.LimitFeature}";
+ }
+ return $"{instance}c:RequiresLimitFeature;f:{context.LimitFeature}";
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisRequiresLimitFeatureChecker.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisRequiresLimitFeatureChecker.cs
index c64feefb9..b3fa32bf9 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisRequiresLimitFeatureChecker.cs
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisRequiresLimitFeatureChecker.cs
@@ -9,7 +9,6 @@ using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
-using Volo.Abp.MultiTenancy;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Features.LimitValidation.Redis
@@ -27,16 +26,16 @@ namespace LINGYUN.Abp.Features.LimitValidation.Redis
private IDatabaseAsync _redis;
private IServer _server;
- private IVirtualFileProvider _virtualFileProvider;
- private ICurrentTenant _currentTenant;
- private AbpRedisRequiresLimitFeatureOptions _options;
+ private readonly IVirtualFileProvider _virtualFileProvider;
+ private readonly IRedisLimitFeatureNamingNormalizer _featureNamingNormalizer;
+ private readonly AbpRedisRequiresLimitFeatureOptions _options;
private readonly string _instance;
private readonly SemaphoreSlim _connectionLock = new SemaphoreSlim(initialCount: 1, maxCount: 1);
public RedisRequiresLimitFeatureChecker(
- ICurrentTenant currentTenant,
IVirtualFileProvider virtualFileProvider,
+ IRedisLimitFeatureNamingNormalizer featureNamingNormalizer,
IOptions optionsAccessor)
{
if (optionsAccessor == null)
@@ -45,8 +44,8 @@ namespace LINGYUN.Abp.Features.LimitValidation.Redis
}
_options = optionsAccessor.Value;
- _currentTenant = currentTenant;
_virtualFileProvider = virtualFileProvider;
+ _featureNamingNormalizer = featureNamingNormalizer;
_instance = _options.InstanceName ?? string.Empty;
@@ -93,11 +92,7 @@ namespace LINGYUN.Abp.Features.LimitValidation.Redis
private string NormalizeKey(RequiresLimitFeatureContext context)
{
- if (_currentTenant.IsAvailable)
- {
- return $"{_instance}t:RequiresLimitFeature;t:{_currentTenant.Id};f:{context.LimitFeature}";
- }
- return $"{_instance}c:RequiresLimitFeature;f:{context.LimitFeature}";
+ return _featureNamingNormalizer.NormalizeFeatureName(_instance, context);
}
private void RegistenConnectionEvent(ConnectionMultiplexer connection)
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
index 879e66df9..6515d7b51 100644
--- 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
@@ -1,4 +1,4 @@
-
+
@@ -8,8 +8,8 @@
-
-
+
+
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
index c6c00aa47..53073bb72 100644
--- 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
@@ -3,6 +3,9 @@ using LINGYUN.Abp.FeatureManagement.Client.Permissions;
using LINGYUN.Abp.Features.Client;
using Volo.Abp.FeatureManagement;
using Volo.Abp.Modularity;
+using Volo.Abp.Localization;
+using Volo.Abp.VirtualFileSystem;
+using Volo.Abp.FeatureManagement.Localization;
namespace LINGYUN.Abp.FeatureManagement
{
@@ -14,11 +17,23 @@ namespace LINGYUN.Abp.FeatureManagement
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
Configure(options =>
{
options.Providers.Add();
- options.ProviderPolicies[ClientFeatureValueProvider.ProviderName] = ClientFeaturePermissionNames.Clients.ManageFeatures;
+ options.ProviderPolicies[ClientFeatureValueProvider.ProviderName] = ClientFeaturePermissionNames.ManageClientFeatures;
+ });
+
+ Configure(options =>
+ {
+ options.Resources
+ .Get()
+ .AddVirtualJson("/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources");
});
}
}
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
index 7a3d08f4a..a7f441917 100644
--- 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
@@ -26,7 +26,7 @@ namespace LINGYUN.Abp.FeatureManagement.Client
{
if (providerKey != null)
{
- base.NormalizeProviderKeyAsync(providerKey);
+ return base.NormalizeProviderKeyAsync(providerKey);
}
return Task.FromResult(CurrentClient.Id);
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources/en.json b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources/en.json
new file mode 100644
index 000000000..8a28af2c2
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources/en.json
@@ -0,0 +1,7 @@
+{
+ "culture": "en",
+ "texts": {
+ "ManageFeatures": "Manage Features",
+ "Permissions:ManageClientFeatures": "Manage Client Features"
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources/zh-Hans.json b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources/zh-Hans.json
new file mode 100644
index 000000000..cc68d615a
--- /dev/null
+++ b/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources/zh-Hans.json
@@ -0,0 +1,7 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+ "ManageFeatures": "管理特性",
+ "Permissions:ManageClientFeatures": "管理客户端特性"
+ }
+}
\ No newline at end of file
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
index 495f23b40..10c57f654 100644
--- 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
@@ -1,4 +1,5 @@
-using Volo.Abp.Authorization.Permissions;
+using Volo.Abp;
+using Volo.Abp.Authorization.Permissions;
using Volo.Abp.FeatureManagement.Localization;
using Volo.Abp.Localization;
@@ -8,21 +9,16 @@ namespace LINGYUN.Abp.FeatureManagement.Client.Permissions
{
public override void Define(IPermissionDefinitionContext context)
{
+ // TODO: 硬编码权限名称还是引用 Volo.Abp.FeatureManagement.Application.Contracts?
+
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);
- }
+ Check.NotNull(identityServerGroup, $"Permissions:{ClientFeaturePermissionNames.GroupName}");
+
identityServerGroup
.AddPermission(
- name: ClientFeaturePermissionNames.Clients.ManageFeatures,
- displayName: L("Permissions:ManageFeatures"),
- multiTenancySide: Volo.Abp.MultiTenancy.MultiTenancySides.Host)
- .WithProviders(ClientPermissionValueProvider.ProviderName);
+ name: ClientFeaturePermissionNames.ManageClientFeatures,
+ displayName: L("Permissions:ManageClientFeatures"),
+ multiTenancySide: Volo.Abp.MultiTenancy.MultiTenancySides.Host);
}
protected virtual LocalizableString L(string 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
index d0b1a7b7e..137fc7efb 100644
--- 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
@@ -2,15 +2,8 @@
{
public class ClientFeaturePermissionNames
{
- public const string GroupName = "IdentityServer";
+ public const string GroupName = "FeatureManagement";
- public static class Clients
- {
- public const string Default = GroupName + ".Clients";
- ///
- /// 管理功能权限
- ///
- public const string ManageFeatures = Default + ".ManageFeatures";
- }
+ public const string ManageClientFeatures = GroupName + ".ManageClientFeatures";
}
}
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
deleted file mode 100644
index 8c72ee646..000000000
--- a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/en.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "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
deleted file mode 100644
index 7f7181c99..000000000
--- a/aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/zh-Hans.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "culture": "zh-Hans",
- "texts": {
- "Permissions:IdentityServer": "IdentityServer管理",
- "ManageFeatures": "管理功能"
- }
-}
\ No newline at end of file
diff --git a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs
index fe052e6c2..19631da06 100644
--- a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs
+++ b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs
@@ -4,16 +4,17 @@ using LINGYUN.Abp.Auditing;
using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Emailing;
-using LINGYUN.Abp.OssManagement;
+using LINGYUN.Abp.FeatureManagement;
using LINGYUN.Abp.MessageService;
using LINGYUN.Abp.MultiTenancy.DbFinder;
+using LINGYUN.Abp.OssManagement;
using LINGYUN.Abp.PermissionManagement.Identity;
using LINGYUN.Abp.SettingManagement;
+using LINGYUN.Abp.Sms.Aliyun;
using LINGYUN.Abp.TenantManagement;
using LINGYUN.Abp.WeChat.SettingManagement;
using LINGYUN.ApiGateway;
using LINGYUN.Platform;
-using LINGYUN.Abp.Sms.Aliyun;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
@@ -80,6 +81,7 @@ namespace LINGYUN.Abp.BackendAdmin
typeof(AbpPermissionManagementHttpApiModule),
typeof(AbpFeatureManagementApplicationModule),
typeof(AbpFeatureManagementHttpApiModule),
+ typeof(AbpFeatureManagementClientModule),
typeof(AbpAuditingApplicationModule),
typeof(AbpAuditingHttpApiModule),
typeof(AbpTenantManagementApplicationModule),
diff --git a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj
index c4ecd9c69..b6890e788 100644
--- a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj
+++ b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj
@@ -66,6 +66,7 @@
+
diff --git a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db
index 0a9a3cae4..d17e999bf 100644
Binary files a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db and b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db differ
diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs
index 19d5080a7..f0a7bbf5d 100644
--- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs
+++ b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs
@@ -81,6 +81,8 @@ namespace LINGYUN.Platform
typeof(AbpEmailingExceptionHandlingModule),
typeof(AbpCAPEventBusModule),
typeof(AbpFeaturesValidationRedisModule),
+ // typeof(AbpFeaturesClientModule),// 当需要客户端特性限制时取消注释此模块
+ // typeof(AbpFeaturesValidationRedisClientModule),// 当需要客户端特性限制时取消注释此模块
typeof(AbpDbFinderMultiTenancyModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAutofacModule)
diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
index 28746c0fe..fe5db99af 100644
--- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
+++ b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
@@ -53,8 +53,9 @@
-
+
+
diff --git a/vueJs/src/api/oss-manager.ts b/vueJs/src/api/oss-manager.ts
index d5b705d13..9a63f94f2 100644
--- a/vueJs/src/api/oss-manager.ts
+++ b/vueJs/src/api/oss-manager.ts
@@ -101,6 +101,10 @@ export default class OssManager {
}
return _url
}
+
+ public static generateDownloadUrl(bucket: string, object: string, path: string = '') {
+ return this.generateOssUrl(bucket, object, path, serviceUrl)
+ }
}
export class GetOssContainerRequest extends PagedAndSortedResultRequestDto {
diff --git a/vueJs/src/views/admin/identityServer/client/components/ClientFeatureEditForm.vue b/vueJs/src/views/admin/identityServer/client/components/ClientFeatureEditForm.vue
new file mode 100644
index 000000000..b423c4447
--- /dev/null
+++ b/vueJs/src/views/admin/identityServer/client/components/ClientFeatureEditForm.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
diff --git a/vueJs/src/views/admin/identityServer/client/index.vue b/vueJs/src/views/admin/identityServer/client/index.vue
index afbc569c3..05a08fab5 100644
--- a/vueJs/src/views/admin/identityServer/client/index.vue
+++ b/vueJs/src/views/admin/identityServer/client/index.vue
@@ -200,6 +200,12 @@
>
{{ $t('AbpIdentityServer.Permissions') }}
+
+ {{ $t('AbpFeatureManagement.ManageFeatures') }}
+
+
+
@@ -270,6 +282,7 @@ import ClientCloneForm from './components/ClientCloneForm.vue'
import PermissionForm from '@/components/PermissionForm/index.vue'
import ClientCreateForm from './components/ClientCreateForm.vue'
import ClientEditForm from './components/ClientEditForm.vue'
+import ClientFeatureEditForm from './components/ClientFeatureEditForm.vue'
import IdentityServer4Service from '@/api/identity-server4'
import ClientService, { Client, ClientGetByPaged } from '@/api/clients'
@@ -281,7 +294,8 @@ import ClientService, { Client, ClientGetByPaged } from '@/api/clients'
PermissionForm,
ClientEditForm,
ClientCloneForm,
- ClientCreateForm
+ ClientCreateForm,
+ ClientFeatureEditForm
},
methods: {
checkPermission,
@@ -306,6 +320,7 @@ export default class extends mixins(DataListMiXin, HttpProxyMiXin) {
private showCreateClientDialog = false
private showCloneClientDialog = false
private showEditClientPermissionDialog = false
+ private showManageClientFeatureDialog = false
public dataFilter = new ClientGetByPaged()
private supportedGrantypes = new Array()
@@ -395,6 +410,9 @@ export default class extends mixins(DataListMiXin, HttpProxyMiXin) {
case 'permissions':
this.showEditClientPermissionDialog = true
break
+ case 'features':
+ this.showManageClientFeatureDialog = true
+ break
case 'delete' :
this.handleDeleteClient(command.row.id, command.row.clientId)
break
diff --git a/vueJs/src/views/oss-management/index.vue b/vueJs/src/views/oss-management/index.vue
index a1abdbd14..1e25761f7 100644
--- a/vueJs/src/views/oss-management/index.vue
+++ b/vueJs/src/views/oss-management/index.vue
@@ -363,7 +363,7 @@ export default class OssManagement extends Vue {
if (!oss.isFolder) {
const link = document.createElement('a')
link.style.display = 'none'
- link.href = OssManagerApi.generateOssUrl(this.bucket, oss.name, oss.path)
+ link.href = OssManagerApi.generateDownloadUrl(this.bucket, oss.name, oss.path)
link.setAttribute('download', oss.name)
document.body.appendChild(link)
link.click()