From abaab0289a96bb2ced6ce8ebb51c5ea06e00b709 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 18 Mar 2021 14:32:21 +0800 Subject: [PATCH] Create interceptor for global features Resolve #8188 --- .../GlobalFeatureActionFilter.cs | 17 +++--- .../GlobalFeatures/GlobalFeaturePageFilter.cs | 17 +++--- .../Abp/Aspects/AbpCrossCuttingConcerns.cs | 1 + .../Volo.Abp.Ddd.Application.csproj | 1 + .../Application/AbpDddApplicationModule.cs | 4 +- .../Services/ApplicationService.cs | 2 + .../Volo.Abp.GlobalFeatures.csproj | 7 +++ .../AbpGlobalFeatureErrorCodes.cs | 7 +++ .../AbpGlobalFeatureNotEnableException.cs | 22 +++++++ .../GlobalFeatures/AbpGlobalFeaturesModule.cs | 35 ++++++++++- .../Abp/GlobalFeatures/GlobalFeatureHelper.cs | 14 +++++ .../GlobalFeatureInterceptor.cs | 28 +++++++++ .../GlobalFeatureInterceptorRegistrar.cs | 22 +++++++ .../IGlobalFeatureCheckingEnabled.cs | 7 +++ .../Localization/AbpGlobalFeatureResource.cs | 10 +++ .../Abp/GlobalFeatures/Localization/en.json | 6 ++ .../Abp/GlobalFeatures/Localization/tr.json | 6 ++ .../GlobalFeatures/Localization/zh-Hans.json | 6 ++ .../GlobalFeatures/Localization/zh-Hant.json | 6 ++ .../Volo.Abp.GlobalFeatures.Tests.csproj | 5 +- ...ureNotEnableException_Localization_Test.cs | 30 +++++++++ .../GlobalFeatureInterceptor_Tests.cs | 61 +++++++++++++++++++ .../GlobalFeatureManager_Tests.cs | 12 ++-- .../GlobalFeatures/GlobalFeatureTestBase.cs | 12 ++++ .../GlobalFeatures/GlobalFeatureTestModule.cs | 16 +++++ .../Volo/Abp/GlobalFeatures/TestFeature.cs | 27 ++++++++ 26 files changed, 352 insertions(+), 29 deletions(-) create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeatureErrorCodes.cs create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeatureNotEnableException.cs create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureHelper.cs create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptor.cs create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptorRegistrar.cs create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/IGlobalFeatureCheckingEnabled.cs create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/AbpGlobalFeatureResource.cs create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/en.json create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/tr.json create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/zh-Hans.json create mode 100644 framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/zh-Hant.json create mode 100644 framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/AbpGlobalFeatureNotEnableException_Localization_Test.cs create mode 100644 framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptor_Tests.cs create mode 100644 framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureTestBase.cs create mode 100644 framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureTestModule.cs create mode 100644 framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/TestFeature.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeatureActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeatureActionFilter.cs index 9498b31a3f..bc625bf2c5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeatureActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeatureActionFilter.cs @@ -1,13 +1,13 @@ -using System; +using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Aspects; using Volo.Abp.DependencyInjection; using Volo.Abp.GlobalFeatures; -using Volo.Abp.Reflection; namespace Volo.Abp.AspNetCore.Mvc.GlobalFeatures { @@ -21,7 +21,7 @@ namespace Volo.Abp.AspNetCore.Mvc.GlobalFeatures return; } - if (!IsGlobalFeatureEnabled(context.Controller.GetType(), out var attribute)) + if (!GlobalFeatureHelper.IsGlobalFeatureEnabled(context.Controller.GetType(), out var attribute)) { var logger = context.GetService>(NullLogger.Instance); logger.LogWarning($"The '{context.Controller.GetType().FullName}' controller needs to enable '{attribute.Name}' feature."); @@ -29,13 +29,10 @@ namespace Volo.Abp.AspNetCore.Mvc.GlobalFeatures return; } - await next(); - } - - protected virtual bool IsGlobalFeatureEnabled(Type controllerType, out RequiresGlobalFeatureAttribute attribute) - { - attribute = ReflectionHelper.GetSingleAttributeOrDefault(controllerType); - return attribute == null || GlobalFeatureManager.Instance.IsEnabled(attribute.GetFeatureName()); + using (AbpCrossCuttingConcerns.Applying(context.Controller, AbpCrossCuttingConcerns.GlobalFeatureChecking)) + { + await next(); + } } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeaturePageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeaturePageFilter.cs index a3415f6be8..e30923dc4c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeaturePageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/GlobalFeatures/GlobalFeaturePageFilter.cs @@ -1,13 +1,13 @@ -using System; +using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Aspects; using Volo.Abp.DependencyInjection; using Volo.Abp.GlobalFeatures; -using Volo.Abp.Reflection; namespace Volo.Abp.AspNetCore.Mvc.GlobalFeatures { @@ -26,7 +26,7 @@ namespace Volo.Abp.AspNetCore.Mvc.GlobalFeatures return; } - if (!IsGlobalFeatureEnabled(context.HandlerInstance.GetType(), out var attribute)) + if (!GlobalFeatureHelper.IsGlobalFeatureEnabled(context.HandlerInstance.GetType(), out var attribute)) { var logger = context.GetService>(NullLogger.Instance); logger.LogWarning($"The '{context.HandlerInstance.GetType().FullName}' page needs to enable '{attribute.Name}' feature."); @@ -34,13 +34,10 @@ namespace Volo.Abp.AspNetCore.Mvc.GlobalFeatures return; } - await next(); - } - - protected virtual bool IsGlobalFeatureEnabled(Type controllerType, out RequiresGlobalFeatureAttribute attribute) - { - attribute = ReflectionHelper.GetSingleAttributeOrDefault(controllerType); - return attribute == null || GlobalFeatureManager.Instance.IsEnabled(attribute.GetFeatureName()); + using (AbpCrossCuttingConcerns.Applying(context.HandlerInstance, AbpCrossCuttingConcerns.GlobalFeatureChecking)) + { + await next(); + } } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Aspects/AbpCrossCuttingConcerns.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Aspects/AbpCrossCuttingConcerns.cs index af4df9c68c..c79c42248e 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Aspects/AbpCrossCuttingConcerns.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Aspects/AbpCrossCuttingConcerns.cs @@ -11,6 +11,7 @@ namespace Volo.Abp.Aspects public const string Auditing = "AbpAuditing"; public const string UnitOfWork = "AbpUnitOfWork"; public const string FeatureChecking = "AbpFeatureChecking"; + public const string GlobalFeatureChecking = "AbpGlobalFeatureChecking"; public static void AddApplied(object obj, params string[] concerns) { diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj b/framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj index f88e0f4795..ca69278768 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj +++ b/framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj @@ -19,6 +19,7 @@ + diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs index c5a16ea6bb..f167465a3b 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs @@ -3,6 +3,7 @@ using Volo.Abp.Application.Services; using Volo.Abp.Authorization; using Volo.Abp.Domain; using Volo.Abp.Features; +using Volo.Abp.GlobalFeatures; using Volo.Abp.Http; using Volo.Abp.Http.Modeling; using Volo.Abp.Modularity; @@ -23,7 +24,8 @@ namespace Volo.Abp.Application typeof(AbpAuthorizationModule), typeof(AbpHttpAbstractionsModule), typeof(AbpSettingsModule), - typeof(AbpFeaturesModule) + typeof(AbpFeaturesModule), + typeof(AbpGlobalFeaturesModule) )] public class AbpDddApplicationModule : AbpModule { diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs index 4ac41663e4..922b887bfa 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs @@ -12,6 +12,7 @@ using Volo.Abp.Auditing; using Volo.Abp.Authorization; using Volo.Abp.DependencyInjection; using Volo.Abp.Features; +using Volo.Abp.GlobalFeatures; using Volo.Abp.Guids; using Volo.Abp.Linq; using Volo.Abp.Localization; @@ -31,6 +32,7 @@ namespace Volo.Abp.Application.Services IValidationEnabled, IUnitOfWorkEnabled, IAuditingEnabled, + IGlobalFeatureCheckingEnabled, ITransientDependency { public IAbpLazyServiceProvider LazyServiceProvider { get; set; } diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo.Abp.GlobalFeatures.csproj b/framework/src/Volo.Abp.GlobalFeatures/Volo.Abp.GlobalFeatures.csproj index f4afe8f9f7..a082ba3c6f 100644 --- a/framework/src/Volo.Abp.GlobalFeatures/Volo.Abp.GlobalFeatures.csproj +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo.Abp.GlobalFeatures.csproj @@ -14,8 +14,15 @@ + + + + + + + diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeatureErrorCodes.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeatureErrorCodes.cs new file mode 100644 index 0000000000..e251cdc381 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeatureErrorCodes.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.GlobalFeatures +{ + public class AbpGlobalFeatureErrorCodes + { + public const string GlobalFeatureIsNotEnabled = "Volo.GlobalFeature:010001"; + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeatureNotEnableException.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeatureNotEnableException.cs new file mode 100644 index 0000000000..71dbafba06 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeatureNotEnableException.cs @@ -0,0 +1,22 @@ +using System; +using Volo.Abp.ExceptionHandling; + +namespace Volo.Abp.GlobalFeatures +{ + public class AbpGlobalFeatureNotEnableException : AbpException, IHasErrorCode + { + public string Code { get; } + + public AbpGlobalFeatureNotEnableException(string message = null, string code = null, Exception innerException = null) + : base(message, innerException) + { + Code = code; + } + + public AbpGlobalFeatureNotEnableException WithData(string name, object value) + { + Data[name] = value; + return this; + } + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeaturesModule.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeaturesModule.cs index d537e9f8fd..b861fd7693 100644 --- a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeaturesModule.cs +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/AbpGlobalFeaturesModule.cs @@ -1,9 +1,42 @@ -using Volo.Abp.Modularity; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.GlobalFeatures.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.GlobalFeatures { + [DependsOn( + typeof(AbpLocalizationModule), + typeof(AbpVirtualFileSystemModule) + )] public class AbpGlobalFeaturesModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.OnRegistred(GlobalFeatureInterceptorRegistrar.RegisterIfNeeded); + } + public override void ConfigureServices(ServiceConfigurationContext context) + { + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/Volo/Abp/GlobalFeatures/Localization"); + }); + + Configure(options => + { + options.MapCodeNamespace("Volo.GlobalFeature", typeof(AbpGlobalFeatureResource)); + }); + } } } diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureHelper.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureHelper.cs new file mode 100644 index 0000000000..a03ec7fa0e --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureHelper.cs @@ -0,0 +1,14 @@ +using System; +using Volo.Abp.Reflection; + +namespace Volo.Abp.GlobalFeatures +{ + public static class GlobalFeatureHelper + { + public static bool IsGlobalFeatureEnabled(Type controllerType, out RequiresGlobalFeatureAttribute attribute) + { + attribute = ReflectionHelper.GetSingleAttributeOrDefault(controllerType); + return attribute == null || GlobalFeatureManager.Instance.IsEnabled(attribute.GetFeatureName()); + } + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptor.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptor.cs new file mode 100644 index 0000000000..e688e18661 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptor.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using Volo.Abp.Aspects; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; + +namespace Volo.Abp.GlobalFeatures +{ + public class GlobalFeatureInterceptor : AbpInterceptor, ITransientDependency + { + public override async Task InterceptAsync(IAbpMethodInvocation invocation) + { + if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.GlobalFeatureChecking)) + { + await invocation.ProceedAsync(); + return; + } + + if (!GlobalFeatureHelper.IsGlobalFeatureEnabled(invocation.TargetObject.GetType(), out var attribute)) + { + throw new AbpGlobalFeatureNotEnableException(code: AbpGlobalFeatureErrorCodes.GlobalFeatureIsNotEnabled) + .WithData("ServiceName", invocation.TargetObject.GetType().FullName) + .WithData("GlobalFeatureName", attribute.Name); + } + + await invocation.ProceedAsync(); + } + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptorRegistrar.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptorRegistrar.cs new file mode 100644 index 0000000000..c60605cdfc --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptorRegistrar.cs @@ -0,0 +1,22 @@ +using System; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DynamicProxy; + +namespace Volo.Abp.GlobalFeatures +{ + public static class GlobalFeatureInterceptorRegistrar + { + public static void RegisterIfNeeded(IOnServiceRegistredContext context) + { + if (ShouldIntercept(context.ImplementationType)) + { + context.Interceptors.TryAdd(); + } + } + + private static bool ShouldIntercept(Type type) + { + return !DynamicProxyIgnoreTypes.Contains(type) && typeof(IGlobalFeatureCheckingEnabled).IsAssignableFrom(type); + } + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/IGlobalFeatureCheckingEnabled.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/IGlobalFeatureCheckingEnabled.cs new file mode 100644 index 0000000000..bed7fa9a12 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/IGlobalFeatureCheckingEnabled.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.GlobalFeatures +{ + public interface IGlobalFeatureCheckingEnabled + { + + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/AbpGlobalFeatureResource.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/AbpGlobalFeatureResource.cs new file mode 100644 index 0000000000..3c6471f2a6 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/AbpGlobalFeatureResource.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Localization; + +namespace Volo.Abp.GlobalFeatures.Localization +{ + [LocalizationResourceName("AbpGlobalFeature")] + public class AbpGlobalFeatureResource + { + + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/en.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/en.json new file mode 100644 index 0000000000..babf74ee59 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/en.json @@ -0,0 +1,6 @@ +{ + "culture": "en", + "texts": { + "Volo.GlobalFeature:010001": "The '{ServiceName}' service needs to enable '{GlobalFeatureName}' feature." + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/tr.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/tr.json new file mode 100644 index 0000000000..5f1ba62775 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/tr.json @@ -0,0 +1,6 @@ +{ + "culture": "tr", + "texts": { + "Volo.GlobalFeature:010001": "'{ServiceName}' hizmetinin '{GlobalFeatureName}' özelliğini etkinleştirmesi gerekiyor." + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/zh-Hans.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/zh-Hans.json new file mode 100644 index 0000000000..ae55f0ce47 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "culture": "zh-Hans", + "texts": { + "Volo.GlobalFeature:010001": "'{ServiceName}'服务需要启用'{GlobalFeatureName}'功能." + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/zh-Hant.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/zh-Hant.json new file mode 100644 index 0000000000..06af02da65 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/zh-Hant.json @@ -0,0 +1,6 @@ +{ + "culture": "zh-Hant", + "texts": { + "Volo.GlobalFeature:010001": "'{ServiceName}'服務需要啟用'{GlobalFeatureName}'功能." + } +} diff --git a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo.Abp.GlobalFeatures.Tests.csproj b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo.Abp.GlobalFeatures.Tests.csproj index 006e3a0c52..c742d83e1c 100644 --- a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo.Abp.GlobalFeatures.Tests.csproj +++ b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo.Abp.GlobalFeatures.Tests.csproj @@ -8,8 +8,11 @@ - + + + + diff --git a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/AbpGlobalFeatureNotEnableException_Localization_Test.cs b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/AbpGlobalFeatureNotEnableException_Localization_Test.cs new file mode 100644 index 0000000000..62c363ba39 --- /dev/null +++ b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/AbpGlobalFeatureNotEnableException_Localization_Test.cs @@ -0,0 +1,30 @@ +using Shouldly; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.Localization; +using Xunit; + +namespace Volo.Abp.GlobalFeatures +{ + public class AbpGlobalFeatureNotEnableException_Localization_Test : GlobalFeatureTestBase + { + private readonly IExceptionToErrorInfoConverter _exceptionToErrorInfoConverter; + + public AbpGlobalFeatureNotEnableException_Localization_Test() + { + _exceptionToErrorInfoConverter = GetRequiredService(); + } + + [Fact] + public void AbpAuthorizationException_Localization() + { + using (CultureHelper.Use("zh-Hans")) + { + var exception = new AbpGlobalFeatureNotEnableException(code: AbpGlobalFeatureErrorCodes.GlobalFeatureIsNotEnabled) + .WithData("ServiceName", "MyService") + .WithData("GlobalFeatureName", "TestFeature");; + var errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("'MyService'服务需要启用'TestFeature'功能."); + } + } + } +} diff --git a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptor_Tests.cs b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptor_Tests.cs new file mode 100644 index 0000000000..a7e97fbf82 --- /dev/null +++ b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureInterceptor_Tests.cs @@ -0,0 +1,61 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Application.Services; +using Volo.Abp.DependencyInjection; +using Xunit; + +namespace Volo.Abp.GlobalFeatures +{ + public class GlobalFeatureInterceptor_Tests : GlobalFeatureTestBase + { + private readonly TestAppServiceV1 _testAppServiceV1; + private readonly TestAppServiceV2 _testAppServiceV2; + + public GlobalFeatureInterceptor_Tests() + { + _testAppServiceV1 = GetRequiredService(); + _testAppServiceV2 = GetRequiredService(); + } + + [Fact] + public async Task Interceptor_Test() + { + var ex = await Assert.ThrowsAsync(async () => + { + await _testAppServiceV1.TestMethod(); + }); + + ex.Data["ServiceName"].ShouldBe(_testAppServiceV1.GetType().FullName); + ex.Data["GlobalFeatureName"].ShouldBe(TestFeature.Name); + + GlobalFeatureManager.Instance.Enable(TestFeature.Name); + + (await _testAppServiceV1.TestMethod()).ShouldBe(1); + (await _testAppServiceV2.TestMethod()).ShouldBe(1); + } + + public interface ITestAppService : IApplicationService + { + Task TestMethod(); + } + + [RequiresGlobalFeature(TestFeature.Name)] + [ExposeServices(typeof(TestAppServiceV1))] + public class TestAppServiceV1 : ApplicationService, ITestAppService + { + public virtual Task TestMethod() + { + return Task.FromResult(1); + } + } + + [ExposeServices(typeof(TestAppServiceV2))] + public class TestAppServiceV2 : ApplicationService, ITestAppService + { + public virtual Task TestMethod() + { + return Task.FromResult(1); + } + } + } +} diff --git a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureManager_Tests.cs b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureManager_Tests.cs index 6d8e3a9d25..d5c4176ebb 100644 --- a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureManager_Tests.cs +++ b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureManager_Tests.cs @@ -3,21 +3,21 @@ using Xunit; namespace Volo.Abp.GlobalFeatures { - public class GlobalFeatureManager_Tests + public class GlobalFeatureManager_Tests : GlobalFeatureTestBase { - private readonly GlobalFeatureManager _featureManeger; + private readonly GlobalFeatureManager _featureManager; public GlobalFeatureManager_Tests() { - _featureManeger = new GlobalFeatureManager(); + _featureManager = new GlobalFeatureManager(); } [Fact] public void Enable_Feature_By_Name() { - _featureManeger.IsEnabled("Feature1").ShouldBeFalse(); - _featureManeger.Enable("Feature1"); - _featureManeger.IsEnabled("Feature1").ShouldBeTrue(); + _featureManager.IsEnabled("Feature1").ShouldBeFalse(); + _featureManager.Enable("Feature1"); + _featureManager.IsEnabled("Feature1").ShouldBeTrue(); } } } diff --git a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureTestBase.cs b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureTestBase.cs new file mode 100644 index 0000000000..24851a4a3f --- /dev/null +++ b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureTestBase.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Testing; + +namespace Volo.Abp.GlobalFeatures +{ + public abstract class GlobalFeatureTestBase : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + } +} diff --git a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureTestModule.cs b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureTestModule.cs new file mode 100644 index 0000000000..03ee257cc2 --- /dev/null +++ b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/GlobalFeatureTestModule.cs @@ -0,0 +1,16 @@ +using Volo.Abp.Application; +using Volo.Abp.Autofac; +using Volo.Abp.ExceptionHandling; +using Volo.Abp.Modularity; + +namespace Volo.Abp.GlobalFeatures +{ + [DependsOn(typeof(AbpAutofacModule))] + [DependsOn(typeof(AbpGlobalFeaturesModule))] + [DependsOn(typeof(AbpDddApplicationModule))] + [DependsOn(typeof(AbpExceptionHandlingModule))] + public class GlobalFeatureTestModule : AbpModule + { + + } +} diff --git a/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/TestFeature.cs b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/TestFeature.cs new file mode 100644 index 0000000000..6912b521db --- /dev/null +++ b/framework/test/Volo.Abp.GlobalFeatures.Tests/Volo/Abp/GlobalFeatures/TestFeature.cs @@ -0,0 +1,27 @@ +namespace Volo.Abp.GlobalFeatures +{ + [GlobalFeatureName(Name)] + public class TestFeature : Abp.GlobalFeatures.GlobalFeature + { + public const string Name = "TestFeature1"; + + internal TestFeature(TestGlobalModuleFeatures testGlobalModule) + : base(testGlobalModule) + { + + } + } + + public class TestGlobalModuleFeatures : GlobalModuleFeatures + { + public const string ModuleName = "GlobalFeatureTest"; + + public TestFeature Test => GetFeature(); + + public TestGlobalModuleFeatures(GlobalFeatureManager featureManager) + : base(featureManager) + { + AddFeature(new TestFeature(this)); + } + } +}