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()