Browse Source

Merge pull request #222 from colinin/4.2

fixed client-specific features
pull/252/head
cKey 5 years ago
committed by GitHub
parent
commit
34903bd4d1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      aspnet-core/LINGYUN.MicroService.All.sln
  2. 135
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
  3. 135
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
  4. 15
      aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj
  5. 9
      aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN/Abp/Features/LimitValidation/Redis/Client/AbpFeaturesValidationRedisClientModule.cs
  6. 33
      aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN/Abp/Features/LimitValidation/Redis/Client/RedisClientLimitFeatureNamingNormalizer.cs
  7. 7
      aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/IRedisLimitFeatureNamingNormalizer.cs
  8. 25
      aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisLimitFeatureNamingNormalizer.cs
  9. 17
      aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis/LINGYUN/Abp/Features/LimitValidation/Redis/RedisRequiresLimitFeatureChecker.cs
  10. 6
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN.Abp.FeatureManagement.Client.csproj
  11. 17
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/AbpFeatureManagementClientModule.cs
  12. 2
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/ClientFeatureManagementProvider.cs
  13. 7
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources/en.json
  14. 7
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources/zh-Hans.json
  15. 22
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionDefinitionProvider.cs
  16. 11
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Client/Permissions/ClientFeaturePermissionNames.cs
  17. 7
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/en.json
  18. 7
      aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/zh-Hans.json
  19. 6
      aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs
  20. 1
      aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj
  21. BIN
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db
  22. 2
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs
  23. 3
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
  24. 4
      vueJs/src/api/oss-manager.ts
  25. 41
      vueJs/src/views/admin/identityServer/client/components/ClientFeatureEditForm.vue
  26. 20
      vueJs/src/views/admin/identityServer/client/index.vue
  27. 2
      vueJs/src/views/oss-management/index.vue

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

135
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml

@ -183,6 +183,65 @@
<param name="message"></param>
<param name="innerException"></param>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.AbpCAPMessageExtensions">
<summary>
CAP消息扩展
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPMessageExtensions.TryGetTenantId(DotNetCore.CAP.Messages.Message,System.Guid@)">
<summary>
尝试获取消息标头中的租户标识
</summary>
<param name="message"></param>
<param name="tenantId"></param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPMessageExtensions.GetTenantIdOrNull(DotNetCore.CAP.Messages.Message)">
<summary>
获取消息标头中的租户标识
</summary>
<param name="message"></param>
<returns></returns>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker">
<summary>
重写 ISubscribeInvoker 实现 Abp 租户集成
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.#ctor(Microsoft.Extensions.Logging.ILoggerFactory,System.IServiceProvider,DotNetCore.CAP.Serialization.ISerializer,Volo.Abp.MultiTenancy.ICurrentTenant)">
<summary>
AbpCAPSubscribeInvoker
</summary>
<param name="loggerFactory"></param>
<param name="serviceProvider"></param>
<param name="serializer"></param>
<param name="currentTenant"></param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.InvokeAsync(DotNetCore.CAP.Internal.ConsumerContext,System.Threading.CancellationToken)">
<summary>
调用订阅者方法
</summary>
<param name="context"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.GetInstance(System.IServiceProvider,DotNetCore.CAP.Internal.ConsumerContext)">
<summary>
获取事件处理类实例
</summary>
<param name="provider"></param>
<param name="context"></param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.ExecuteWithParameterAsync(LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutor,System.Object,System.Object[])">
<summary>
通过给定的类型实例与参数调用订阅者方法
</summary>
<param name="executor"></param>
<param name="class"></param>
<param name="parameter"></param>
<returns></returns>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus">
<summary>
CAP分布式事件总线
@ -213,14 +272,32 @@
本地事件集合
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,Microsoft.Extensions.Options.IOptions{Volo.Abp.EventBus.Distributed.AbpDistributedEventBusOptions},DotNetCore.CAP.ICapPublisher,Volo.Abp.MultiTenancy.ICurrentTenant,LINGYUN.Abp.EventBus.CAP.ICustomDistributedEventSubscriber)">
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.CurrentUser">
<summary>
当前用户
</summary>
</member>
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.CurrentClient">
<summary>
当前客户端
</summary>
</member>
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.CancellationTokenProvider">
<summary>
取消令牌
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,Microsoft.Extensions.Options.IOptions{Volo.Abp.EventBus.Distributed.AbpDistributedEventBusOptions},DotNetCore.CAP.ICapPublisher,Volo.Abp.Users.ICurrentUser,Volo.Abp.Clients.ICurrentClient,Volo.Abp.MultiTenancy.ICurrentTenant,Volo.Abp.Threading.ICancellationTokenProvider,LINGYUN.Abp.EventBus.CAP.ICustomDistributedEventSubscriber)">
<summary>
constructor
</summary>
<param name="serviceScopeFactory"></param>
<param name="distributedEventBusOptions"></param>
<param name="capPublisher"></param>
<param name="currentUser"></param>
<param name="currentTenant"></param>
<param name="currentClient"></param>
<param name="cancellationTokenProvider"></param>
<param name="customDistributedEventSubscriber"></param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.Subscribe(System.Type,Volo.Abp.EventBus.IEventHandlerFactory)">
@ -300,6 +377,62 @@
<param name="eventType"></param>
<param name="factory"></param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutor.Execute(System.Object,System.Object[])">
<summary>
Executes the configured method on <paramref name="target" />. This can be used whether or not
the configured method is asynchronous.
</summary>
<remarks>
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.
</remarks>
<param name="target">The object whose method is to be executed.</param>
<param name="parameters">Parameters to pass to the method.</param>
<returns>The method return value.</returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutor.ExecuteAsync(System.Object,System.Object[])">
<summary>
Executes the configured method on <paramref name="target" />. This can only be used if the configured
method is asynchronous.
</summary>
<remarks>
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).
</remarks>
<param name="target">The object whose method is to be executed.</param>
<param name="parameters">Parameters to pass to the method.</param>
<returns>An object that you can "await" to get the method return value.</returns>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutorAwaitable">
<summary>
Provides a common awaitable structure that <see cref="M:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutor.ExecuteAsync(System.Object,System.Object[])" /> can
return, regardless of whether the underlying value is a System.Task, an FSharpAsync, or an
application-defined custom awaitable.
</summary>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutorFSharpSupport">
<summary>
Helper for detecting whether a given type is FSharpAsync`1, and if so, supplying
an <see cref="T:System.Linq.Expressions.Expression" /> for mapping instances of that type to a C# awaitable.
</summary>
<remarks>
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.
</remarks>
</member>
<member name="T:Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions">
<summary>
CAP ServiceCollectionExtensions

135
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml

@ -183,6 +183,65 @@
<param name="message"></param>
<param name="innerException"></param>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.AbpCAPMessageExtensions">
<summary>
CAP消息扩展
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPMessageExtensions.TryGetTenantId(DotNetCore.CAP.Messages.Message,System.Guid@)">
<summary>
尝试获取消息标头中的租户标识
</summary>
<param name="message"></param>
<param name="tenantId"></param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPMessageExtensions.GetTenantIdOrNull(DotNetCore.CAP.Messages.Message)">
<summary>
获取消息标头中的租户标识
</summary>
<param name="message"></param>
<returns></returns>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker">
<summary>
重写 ISubscribeInvoker 实现 Abp 租户集成
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.#ctor(Microsoft.Extensions.Logging.ILoggerFactory,System.IServiceProvider,DotNetCore.CAP.Serialization.ISerializer,Volo.Abp.MultiTenancy.ICurrentTenant)">
<summary>
AbpCAPSubscribeInvoker
</summary>
<param name="loggerFactory"></param>
<param name="serviceProvider"></param>
<param name="serializer"></param>
<param name="currentTenant"></param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.InvokeAsync(DotNetCore.CAP.Internal.ConsumerContext,System.Threading.CancellationToken)">
<summary>
调用订阅者方法
</summary>
<param name="context"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.GetInstance(System.IServiceProvider,DotNetCore.CAP.Internal.ConsumerContext)">
<summary>
获取事件处理类实例
</summary>
<param name="provider"></param>
<param name="context"></param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.ExecuteWithParameterAsync(LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutor,System.Object,System.Object[])">
<summary>
通过给定的类型实例与参数调用订阅者方法
</summary>
<param name="executor"></param>
<param name="class"></param>
<param name="parameter"></param>
<returns></returns>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus">
<summary>
CAP分布式事件总线
@ -213,14 +272,32 @@
本地事件集合
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,Microsoft.Extensions.Options.IOptions{Volo.Abp.EventBus.Distributed.AbpDistributedEventBusOptions},DotNetCore.CAP.ICapPublisher,Volo.Abp.MultiTenancy.ICurrentTenant,LINGYUN.Abp.EventBus.CAP.ICustomDistributedEventSubscriber)">
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.CurrentUser">
<summary>
当前用户
</summary>
</member>
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.CurrentClient">
<summary>
当前客户端
</summary>
</member>
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.CancellationTokenProvider">
<summary>
取消令牌
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,Microsoft.Extensions.Options.IOptions{Volo.Abp.EventBus.Distributed.AbpDistributedEventBusOptions},DotNetCore.CAP.ICapPublisher,Volo.Abp.Users.ICurrentUser,Volo.Abp.Clients.ICurrentClient,Volo.Abp.MultiTenancy.ICurrentTenant,Volo.Abp.Threading.ICancellationTokenProvider,LINGYUN.Abp.EventBus.CAP.ICustomDistributedEventSubscriber)">
<summary>
constructor
</summary>
<param name="serviceScopeFactory"></param>
<param name="distributedEventBusOptions"></param>
<param name="capPublisher"></param>
<param name="currentUser"></param>
<param name="currentTenant"></param>
<param name="currentClient"></param>
<param name="cancellationTokenProvider"></param>
<param name="customDistributedEventSubscriber"></param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.Subscribe(System.Type,Volo.Abp.EventBus.IEventHandlerFactory)">
@ -300,6 +377,62 @@
<param name="eventType"></param>
<param name="factory"></param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutor.Execute(System.Object,System.Object[])">
<summary>
Executes the configured method on <paramref name="target" />. This can be used whether or not
the configured method is asynchronous.
</summary>
<remarks>
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.
</remarks>
<param name="target">The object whose method is to be executed.</param>
<param name="parameters">Parameters to pass to the method.</param>
<returns>The method return value.</returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutor.ExecuteAsync(System.Object,System.Object[])">
<summary>
Executes the configured method on <paramref name="target" />. This can only be used if the configured
method is asynchronous.
</summary>
<remarks>
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).
</remarks>
<param name="target">The object whose method is to be executed.</param>
<param name="parameters">Parameters to pass to the method.</param>
<returns>An object that you can "await" to get the method return value.</returns>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutorAwaitable">
<summary>
Provides a common awaitable structure that <see cref="M:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutor.ExecuteAsync(System.Object,System.Object[])" /> can
return, regardless of whether the underlying value is a System.Task, an FSharpAsync, or an
application-defined custom awaitable.
</summary>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.Internal.ObjectMethodExecutorFSharpSupport">
<summary>
Helper for detecting whether a given type is FSharpAsync`1, and if so, supplying
an <see cref="T:System.Linq.Expressions.Expression" /> for mapping instances of that type to a C# awaitable.
</summary>
<remarks>
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.
</remarks>
</member>
<member name="T:Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions">
<summary>
CAP ServiceCollectionExtensions

15
aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation.Redis.Client/LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
<Description>功能限制验证组件Redis客户端格式实现</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Features.LimitValidation.Redis\LINGYUN.Abp.Features.LimitValidation.Redis.csproj" />
</ItemGroup>
</Project>

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

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

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

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

17
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<AbpRedisRequiresLimitFeatureOptions> 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)

6
aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN.Abp.FeatureManagement.Client.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
@ -8,8 +8,8 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\FeatureManagement\Localization\Client\*.json" />
<Content Remove="LINGYUN\Abp\FeatureManagement\Localization\Client\*.json" />
<EmbeddedResource Include="LINGYUN\Abp\FeatureManagement\Client\Localization\Resources\*.json" />
<Content Remove="LINGYUN\Abp\FeatureManagement\Client\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>

17
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<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpFeatureManagementClientModule>();
});
Configure<FeatureManagementOptions>(options =>
{
options.Providers.Add<ClientFeatureManagementProvider>();
options.ProviderPolicies[ClientFeatureValueProvider.ProviderName] = ClientFeaturePermissionNames.Clients.ManageFeatures;
options.ProviderPolicies[ClientFeatureValueProvider.ProviderName] = ClientFeaturePermissionNames.ManageClientFeatures;
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpFeatureManagementResource>()
.AddVirtualJson("/LINGYUN/Abp/FeatureManagement/Client/Localization/Resources");
});
}
}

2
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);

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

7
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": "管理客户端特性"
}
}

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

11
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";
/// <summary>
/// 管理功能权限
/// </summary>
public const string ManageFeatures = Default + ".ManageFeatures";
}
public const string ManageClientFeatures = GroupName + ".ManageClientFeatures";
}
}

7
aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/en.json

@ -1,7 +0,0 @@
{
"culture": "en",
"texts": {
"Permissions:IdentityServer": "IdentityServer",
"Permissions:ManageFeatures": "Manage features"
}
}

7
aspnet-core/modules/features/LINGYUN.Abp.FeatureManagement.Client/LINGYUN/Abp/FeatureManagement/Localization/Client/zh-Hans.json

@ -1,7 +0,0 @@
{
"culture": "zh-Hans",
"texts": {
"Permissions:IdentityServer": "IdentityServer管理",
"ManageFeatures": "管理功能"
}
}

6
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),

1
aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj

@ -66,6 +66,7 @@
<ProjectReference Include="..\..\..\modules\cloud-aliyun\LINGYUN.Abp.Aliyun.SettingManagement\LINGYUN.Abp.Aliyun.SettingManagement.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj" />
<ProjectReference Include="..\..\..\modules\features\LINGYUN.Abp.FeatureManagement.Client\LINGYUN.Abp.FeatureManagement.Client.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\modules\identityServer\LINGYUN.Abp.IdentityServer.Application.Contracts\LINGYUN.Abp.IdentityServer.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\modules\identity\LINGYUN.Abp.Identity.Application.Contracts\LINGYUN.Abp.Identity.Application.Contracts.csproj" />

BIN
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db

Binary file not shown.

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

3
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj

@ -53,8 +53,9 @@
<ItemGroup>
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.Features.LimitValidation.Redis\LINGYUN.Abp.Features.LimitValidation.Redis.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.Features.LimitValidation.Redis.Client\LINGYUN.Abp.Features.LimitValidation.Redis.Client.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" />
<ProjectReference Include="..\..\..\modules\features\LINGYUN.Abp.Features.Client\LINGYUN.Abp.Features.Client.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.Aliyun\LINGYUN.Abp.OssManagement.Aliyun.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.Application\LINGYUN.Abp.OssManagement.Application.csproj" />
<ProjectReference Include="..\..\..\modules\oss-management\LINGYUN.Abp.OssManagement.FileSystem.ImageSharp\LINGYUN.Abp.OssManagement.FileSystem.ImageSharp.csproj" />

4
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 {

41
vueJs/src/views/admin/identityServer/client/components/ClientFeatureEditForm.vue

@ -0,0 +1,41 @@
<template>
<el-dialog
:visible="showDialog"
:title="$t('AbpFeatureManagement.ManageFeatures')"
width="800px"
custom-class="modal-form"
:show-close="false"
@close="onFormClosed"
>
<feature-management
ref="featureManagement"
provider-name="C"
:provider-key="clientId"
:load-feature="showDialog"
@closed="onFormClosed"
/>
</el-dialog>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import FeatureManagement from '../../../components/FeatureManagement.vue'
@Component({
name: 'ClientFeatureEditForm',
components: {
FeatureManagement
}
})
export default class extends Vue {
@Prop({ default: '' })
private clientId!: string
@Prop({ default: false })
private showDialog!: boolean
private onFormClosed() {
this.$emit('closed')
}
}
</script>

20
vueJs/src/views/admin/identityServer/client/index.vue

@ -200,6 +200,12 @@
>
{{ $t('AbpIdentityServer.Permissions') }}
</el-dropdown-item>
<el-dropdown-item
v-permission="['FeatureManagement.ManageHostFeatures']"
:command="{key: 'features', row}"
>
{{ $t('AbpFeatureManagement.ManageFeatures') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'clone', row}"
:disabled="!checkPermission(['AbpIdentityServer.Clients.Clone'])"
@ -255,6 +261,12 @@
:show-dialog="showEditClientDialog"
@closed="onEditClientDialogClosed"
/>
<client-feature-edit-form
:show-dialog="showManageClientFeatureDialog"
:client-id="editClient.clientId"
@closed="showManageClientFeatureDialog=false"
/>
</div>
</template>
@ -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<string>()
@ -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

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

Loading…
Cancel
Save