diff --git a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs index 45650b06a4..86d18b4309 100644 --- a/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs +++ b/framework/src/Volo.Abp.Authorization/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions.cs @@ -95,7 +95,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(policyName)) { - throw new AbpAuthorizationException("Authorization failed! Given policy has not granted: " + policyName); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedWithPolicyName) + .WithData("PolicyName", policyName); } } @@ -103,7 +104,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(resource, requirement)) { - throw new AbpAuthorizationException("Authorization failed! Given requirement has not granted for given resource: " + resource); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenRequirementHasNotGrantedForGivenResource) + .WithData("PolicyName", resource); } } @@ -111,7 +113,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(resource, policy)) { - throw new AbpAuthorizationException("Authorization failed! Given policy has not granted for given resource: " + resource); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedForGivenResource) + .WithData("ResourceName", resource); } } @@ -119,7 +122,7 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(policy)) { - throw new AbpAuthorizationException("Authorization failed! Given policy has not granted."); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGranted); } } @@ -127,7 +130,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(resource, requirements)) { - throw new AbpAuthorizationException("Authorization failed! Given requirements have not granted for given resource: " + resource); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenRequirementsHasNotGrantedForGivenResource) + .WithData("ResourceName", resource); } } @@ -135,7 +139,8 @@ namespace Microsoft.AspNetCore.Authorization { if (!await authorizationService.IsGrantedAsync(resource, policyName)) { - throw new AbpAuthorizationException("Authorization failed! Given polist has not granted for given resource: " + resource); + throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedForGivenResource) + .WithData("ResourceName", resource); } } @@ -149,4 +154,4 @@ namespace Microsoft.AspNetCore.Authorization return abpAuthorizationService; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj b/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj index 9e355531fa..66dd574322 100644 --- a/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj +++ b/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj @@ -19,7 +19,12 @@ - + + + + + + diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationErrorCodes.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationErrorCodes.cs new file mode 100644 index 0000000000..0d4562eba3 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationErrorCodes.cs @@ -0,0 +1,15 @@ +namespace Volo.Abp.Authorization +{ + public static class AbpAuthorizationErrorCodes + { + public const string GivenPolicyHasNotGranted = "Volo.Authorization:010001"; + + public const string GivenPolicyHasNotGrantedWithPolicyName = "Volo.Authorization:010002"; + + public const string GivenPolicyHasNotGrantedForGivenResource = "Volo.Authorization:010003"; + + public const string GivenRequirementHasNotGrantedForGivenResource = "Volo.Authorization:010004"; + + public const string GivenRequirementsHasNotGrantedForGivenResource = "Volo.Authorization:010005"; + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs index b16e08a214..b4d5795b9c 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs @@ -3,17 +3,20 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.Authorization.Localization; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.Security; +using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.Authorization { [DependsOn( typeof(AbpSecurityModule), - typeof(AbpLocalizationAbstractionsModule), + typeof(AbpLocalizationModule), typeof(AbpMultiTenancyModule) )] public class AbpAuthorizationModule : AbpModule @@ -38,6 +41,23 @@ namespace Volo.Abp.Authorization options.ValueProviders.Add(); options.ValueProviders.Add(); }); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/Volo/Abp/Authorization/Localization"); + }); + + Configure(options => + { + options.MapCodeNamespace("Volo.Authorization", typeof(AbpAuthorizationResource)); + }); } private static void AutoAddDefinitionProviders(IServiceCollection services) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/AbpAuthorizationResource.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/AbpAuthorizationResource.cs new file mode 100644 index 0000000000..2888509915 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/AbpAuthorizationResource.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Localization; + +namespace Volo.Abp.Authorization.Localization +{ + [LocalizationResourceName("AbpAuthorization")] + public class AbpAuthorizationResource + { + + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/en.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/en.json new file mode 100644 index 0000000000..e7bc77c341 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/en.json @@ -0,0 +1,10 @@ +{ + "culture": "en", + "texts": { + "Volo.Authorization:010001": "Authorization failed! Given policy has not granted.", + "Volo.Authorization:010002": "Authorization failed! Given policy has not granted: {PolicyName}", + "Volo.Authorization:010003": "Authorization failed! Given policy has not granted for given resource: {ResourceName}", + "Volo.Authorization:010004": "Authorization failed! Given requirement has not granted for given resource: {ResourceName}", + "Volo.Authorization:010005": "Authorization failed! Given requirements has not granted for given resource: {ResourceName}" + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/tr.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/tr.json new file mode 100644 index 0000000000..03ca832432 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/tr.json @@ -0,0 +1,10 @@ +{ + "culture": "tr", + "texts": { + "Volo.Authorization:010001": "Yetkilendirme başarısız oldu! Verilen politika verilmemiştir.", + "Volo.Authorization:010002": "Yetkilendirme başarısız oldu! Verilen politika vermedi: {PolicyName}", + "Volo.Authorization:010003": "Yetkilendirme başarısız oldu! Verilen politika, verilen kaynak için verilmemiştir: {ResourceName}", + "Volo.Authorization:010004": "Yetkilendirme başarısız oldu! Belirtilen kaynak için verilen şart verilmedi {ResourceName}", + "Volo.Authorization:010005": "Yetkilendirme başarısız oldu! Verilen gereksinimler, verilen kaynak için verilmemiştir: {ResourceName}" + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/zh-Hans.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/zh-Hans.json new file mode 100644 index 0000000000..d0946ef6a5 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/zh-Hans.json @@ -0,0 +1,10 @@ +{ + "culture": "zh-Hans", + "texts": { + "Volo.Authorization:010001": "授权失败! 提供的策略尚未授予.", + "Volo.Authorization:010002": "授权失败! 提供的策略尚未授予: {PolicyName}", + "Volo.Authorization:010003": "授权失败! 提供的策略未授予提供的资源: {ResourceName}", + "Volo.Authorization:010004": "授权失败! 提供的要求未授予提供的资源: {ResourceName}", + "Volo.Authorization:010005": "授权失败! 提供的要求未授予提供的资源: {ResourceName}" + } +} diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs index 6367bd24ff..eb8c4eb804 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs @@ -62,12 +62,6 @@ namespace Volo.Abp.AspNetCore.ExceptionHandling return CreateEntityNotFoundError(exception as EntityNotFoundException); } - if (exception is AbpAuthorizationException) - { - var authorizationException = exception as AbpAuthorizationException; - return new RemoteServiceErrorInfo(authorizationException.Message); - } - var errorInfo = new RemoteServiceErrorInfo(); if (exception is IUserFriendlyException) diff --git a/framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj b/framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj index a2d098f970..3bea3ea77f 100644 --- a/framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj +++ b/framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj @@ -15,7 +15,12 @@ - + + + + + + diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeatureErrorCodes.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeatureErrorCodes.cs new file mode 100644 index 0000000000..a5a4cf3a58 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeatureErrorCodes.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Features +{ + public static class AbpFeatureErrorCodes + { + public const string FeatureIsNotEnabled = "Volo.Feature:010001"; + + public const string AllOfTheseFeaturesMustBeEnabled = "Volo.Feature:010002"; + + public const string AtLeastOneOfTheseFeaturesMustBeEnabled = "Volo.Feature:010003"; + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs index f30017feed..70c6e7f37d 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs @@ -1,15 +1,18 @@ using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; +using Volo.Abp.Features.Localization; using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.Validation; +using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.Features { [DependsOn( - typeof(AbpLocalizationAbstractionsModule), + typeof(AbpLocalizationModule), typeof(AbpMultiTenancyModule), typeof(AbpValidationModule) )] @@ -29,6 +32,23 @@ namespace Volo.Abp.Features options.ValueProviders.Add(); options.ValueProviders.Add(); }); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/Volo/Abp/Features/Localization"); + }); + + Configure(options => + { + options.MapCodeNamespace("Volo.Feature", typeof(AbpFeatureResource)); + }); } private static void AutoAddDefinitionProviders(IServiceCollection services) diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs index 8850408df0..ba2b640031 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureCheckerExtensions.cs @@ -9,8 +9,8 @@ namespace Volo.Abp.Features public static class FeatureCheckerExtensions { public static async Task GetAsync( - [NotNull] this IFeatureChecker featureChecker, - [NotNull] string name, + [NotNull] this IFeatureChecker featureChecker, + [NotNull] string name, T defaultValue = default) where T : struct { @@ -56,10 +56,11 @@ namespace Volo.Abp.Features { if (!(await featureChecker.IsEnabledAsync(featureName))) { - throw new AbpAuthorizationException("Feature is not enabled: " + featureName); + throw new AbpAuthorizationException(code: AbpFeatureErrorCodes.FeatureIsNotEnabled).WithData( + "FeatureName", featureName); } } - + public static async Task CheckEnabledAsync(this IFeatureChecker featureChecker, bool requiresAll, params string[] featureNames) { if (featureNames.IsNullOrEmpty()) @@ -73,10 +74,8 @@ namespace Volo.Abp.Features { if (!(await featureChecker.IsEnabledAsync(featureName))) { - throw new AbpAuthorizationException( - "Required features are not enabled. All of these features must be enabled: " + - string.Join(", ", featureNames) - ); + throw new AbpAuthorizationException(code: AbpFeatureErrorCodes.AllOfTheseFeaturesMustBeEnabled) + .WithData("FeatureNames", string.Join(", ", featureNames)); } } } @@ -90,11 +89,9 @@ namespace Volo.Abp.Features } } - throw new AbpAuthorizationException( - "Required features are not enabled. At least one of these features must be enabled: " + - string.Join(", ", featureNames) - ); + throw new AbpAuthorizationException(code: AbpFeatureErrorCodes.AtLeastOneOfTheseFeaturesMustBeEnabled) + .WithData("FeatureNames", string.Join(", ", featureNames)); } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/AbpFeatureResource.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/AbpFeatureResource.cs new file mode 100644 index 0000000000..5871d550ad --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/AbpFeatureResource.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Localization; + +namespace Volo.Abp.Features.Localization +{ + [LocalizationResourceName("AbpFeature")] + public class AbpFeatureResource + { + + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/en.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/en.json new file mode 100644 index 0000000000..de03dc11d0 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/en.json @@ -0,0 +1,8 @@ +{ + "culture": "en", + "texts": { + "Volo.Feature:010001": "Feature is not enabled: {FeatureName}", + "Volo.Feature:010002": "Required features are not enabled. All of these features must be enabled: {FeatureNames}", + "Volo.Feature:010003": "Required features are not enabled. At least one of these features must be enabled: {FeatureNames}" + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/tr.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/tr.json new file mode 100644 index 0000000000..9277b63530 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/tr.json @@ -0,0 +1,8 @@ +{ + "culture": "tr", + "texts": { + "Volo.Feature:010001": "Özellik etkinleştirilmedi: {FeatureName}", + "Volo.Feature:010002": "Gerekli özellikler etkinleştirilmedi. Bu özelliklerin tümü etkinleştirilmelidir: {FeatureNames}", + "Volo.Feature:010003": "Gerekli özellikler etkinleştirilmedi. Bu özelliklerden en az birinin etkinleştirilmesi gerekir: {FeatureNames}" + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/zh-Hans.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/zh-Hans.json new file mode 100644 index 0000000000..4c6d99c281 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/zh-Hans.json @@ -0,0 +1,8 @@ +{ + "culture": "zh-Hans", + "texts": { + "Volo.Feature:010001": "功能未启用: {FeatureName}", + "Volo.Feature:010002": "必要的功能未启用. 这些功能需要启用: {FeatureNames}", + "Volo.Feature:010003": "必要的功能未启用. 需要启用这些功能中的一项:{FeatureNames}" + } +} diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs index ad5b0b65a3..c0a8c4d4f8 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.Serialization; using Microsoft.Extensions.Logging; +using Volo.Abp.ExceptionHandling; using Volo.Abp.Logging; namespace Volo.Abp.Authorization @@ -9,7 +10,7 @@ namespace Volo.Abp.Authorization /// This exception is thrown on an unauthorized request. /// [Serializable] - public class AbpAuthorizationException : AbpException, IHasLogLevel + public class AbpAuthorizationException : AbpException, IHasLogLevel, IHasErrorCode { /// /// Severity of the exception. @@ -17,6 +18,11 @@ namespace Volo.Abp.Authorization /// public LogLevel LogLevel { get; set; } + /// + /// Error code. + /// + public string Code { get; } + /// /// Creates a new object. /// @@ -54,5 +60,24 @@ namespace Volo.Abp.Authorization { LogLevel = LogLevel.Warning; } + + /// + /// Creates a new object. + /// + /// Exception message + /// Exception code + /// Inner exception + public AbpAuthorizationException(string message = null, string code = null, Exception innerException = null) + : base(message, innerException) + { + Code = code; + LogLevel = LogLevel.Warning; + } + + public AbpAuthorizationException WithData(string name, object value) + { + Data[name] = value; + return this; + } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Authorization.Tests/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions_Tests.cs new file mode 100644 index 0000000000..e8876aaebf --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions_Tests.cs @@ -0,0 +1,49 @@ +using Shouldly; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.Authorization; +using Volo.Abp.Localization; +using Xunit; + +namespace Microsoft.AspNetCore.Authorization +{ + public class AbpAuthorizationServiceExtensions_Tests : AuthorizationTestBase + { + private readonly IExceptionToErrorInfoConverter _exceptionToErrorInfoConverter; + + public AbpAuthorizationServiceExtensions_Tests() + { + _exceptionToErrorInfoConverter = GetRequiredService(); + } + + [Fact] + public void Test_AbpAuthorizationException_Localization() + { + using (CultureHelper.Use("zh-Hans")) + { + var exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGranted); + var errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的策略尚未授予."); + + exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedWithPolicyName) + .WithData("PolicyName", "my_policy_name"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的策略尚未授予: my_policy_name"); + + exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGrantedForGivenResource) + .WithData("ResourceName", "my_resource_name"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的策略未授予提供的资源: my_resource_name"); + + exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenRequirementHasNotGrantedForGivenResource) + .WithData("ResourceName", "my_resource_name"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的要求未授予提供的资源: my_resource_name"); + + exception = new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenRequirementsHasNotGrantedForGivenResource) + .WithData("ResourceName", "my_resource_name"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("授权失败! 提供的要求未授予提供的资源: my_resource_name"); + } + } + } +} diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj index 165aaaa1d0..279523610e 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj @@ -12,6 +12,7 @@ + diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs index 492a36f8b9..69417e48c6 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs @@ -2,12 +2,14 @@ using Volo.Abp.Authorization.TestServices; using Volo.Abp.Autofac; using Volo.Abp.DynamicProxy; +using Volo.Abp.ExceptionHandling; using Volo.Abp.Modularity; namespace Volo.Abp.Authorization { [DependsOn(typeof(AbpAutofacModule))] [DependsOn(typeof(AbpAuthorizationModule))] + [DependsOn(typeof(AbpExceptionHandlingModule))] public class AbpAuthorizationTestModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) @@ -22,4 +24,4 @@ namespace Volo.Abp.Authorization }); } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj index 3edc355ca2..713b541431 100644 --- a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj +++ b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/AbpFeaturesTestModule.cs b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/AbpFeaturesTestModule.cs index 7b0927b80d..f5ff20e6f2 100644 --- a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/AbpFeaturesTestModule.cs +++ b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/AbpFeaturesTestModule.cs @@ -1,10 +1,12 @@ using Volo.Abp.Autofac; +using Volo.Abp.ExceptionHandling; using Volo.Abp.Modularity; namespace Volo.Abp.Features { [DependsOn( typeof(AbpFeaturesModule), + typeof(AbpExceptionHandlingModule), typeof(AbpTestBaseModule), typeof(AbpAutofacModule) )] @@ -12,7 +14,7 @@ namespace Volo.Abp.Features { public override void ConfigureServices(ServiceConfigurationContext context) { - + } } } diff --git a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs new file mode 100644 index 0000000000..0df9548f3c --- /dev/null +++ b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs @@ -0,0 +1,40 @@ +using Shouldly; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.Authorization; +using Volo.Abp.Localization; +using Xunit; + +namespace Volo.Abp.Features +{ + public class FeatureCheckerExtensions_Tests : FeatureTestBase + { + private readonly IExceptionToErrorInfoConverter _exceptionToErrorInfoConverter; + + public FeatureCheckerExtensions_Tests() + { + _exceptionToErrorInfoConverter = GetRequiredService(); + } + + [Fact] + public void Test_AbpAuthorizationException_Localization() + { + using (CultureHelper.Use("zh-Hans")) + { + var exception = new AbpAuthorizationException(code: AbpFeatureErrorCodes.FeatureIsNotEnabled) + .WithData("FeatureName", "my_feature_name"); + var errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("功能未启用: my_feature_name"); + + exception = new AbpAuthorizationException(code: AbpFeatureErrorCodes.AllOfTheseFeaturesMustBeEnabled) + .WithData("FeatureNames", "my_feature_name, my_feature_name2"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("必要的功能未启用. 这些功能需要启用: my_feature_name, my_feature_name2"); + + exception = new AbpAuthorizationException(code: AbpFeatureErrorCodes.AtLeastOneOfTheseFeaturesMustBeEnabled) + .WithData("FeatureNames", "my_feature_name, my_feature_name2"); + errorInfo = _exceptionToErrorInfoConverter.Convert(exception, false); + errorInfo.Message.ShouldBe("必要的功能未启用. 需要启用这些功能中的一项:my_feature_name, my_feature_name2"); + } + } + } +}