From f5d0d2549a2f5ea7e43d5cd25e582cbfbad3ca03 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Thu, 3 Dec 2020 17:38:58 +0300 Subject: [PATCH 1/6] ABP CLI: Use app-pro template by default if developer has an active license related https://github.com/volosoft/volo/issues/4193 --- .../Volo/Abp/Cli/Commands/NewCommand.cs | 9 ++- .../ProjectBuilding/ITemplateInfoProvider.cs | 5 +- .../ProjectBuilding/TemplateInfoProvider.cs | 61 ++++++++++++++++++- .../ProjectBuilding/TemplateProjectBuilder.cs | 6 +- 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 01807bc0ff..75d2651cbc 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -3,18 +3,22 @@ using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using ICSharpCode.SharpZipLib.Core; using ICSharpCode.SharpZipLib.Zip; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Auth; +using Volo.Abp.Cli.Http; using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Templates.App; using Volo.Abp.Cli.ProjectBuilding.Templates.Console; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.Cli.Commands { @@ -25,7 +29,8 @@ namespace Volo.Abp.Cli.Commands protected TemplateProjectBuilder TemplateProjectBuilder { get; } public ITemplateInfoProvider TemplateInfoProvider { get; } - public NewCommand(TemplateProjectBuilder templateProjectBuilder, ITemplateInfoProvider templateInfoProvider) + public NewCommand(TemplateProjectBuilder templateProjectBuilder + , ITemplateInfoProvider templateInfoProvider) { TemplateProjectBuilder = templateProjectBuilder; TemplateInfoProvider = templateInfoProvider; @@ -193,7 +198,7 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation($"'{projectName}' has been successfully created to '{outputFolder}'"); - if (AppTemplateBase.IsAppTemplate(template ?? TemplateInfoProvider.GetDefault().Name)) + if (AppTemplateBase.IsAppTemplate(template ?? (await TemplateInfoProvider.GetDefaultAsync()).Name)) { var isCommercial = template == AppProTemplate.TemplateName; OpenThanksPage(uiFramework, databaseProvider, isTiered || commandLineArgs.Options.ContainsKey("separate-identity-server"), isCommercial); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs index 5330bc9962..55db4cd11a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateInfoProvider.cs @@ -1,10 +1,11 @@ -using Volo.Abp.Cli.ProjectBuilding.Building; +using System.Threading.Tasks; +using Volo.Abp.Cli.ProjectBuilding.Building; namespace Volo.Abp.Cli.ProjectBuilding { public interface ITemplateInfoProvider { - TemplateInfo GetDefault(); + Task GetDefaultAsync(); TemplateInfo Get(string name); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs index 7a4df335fe..269795d4a4 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs @@ -1,18 +1,44 @@ using System; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Auth; +using Volo.Abp.Cli.Http; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Templates.App; using Volo.Abp.Cli.ProjectBuilding.Templates.Console; using Volo.Abp.Cli.ProjectBuilding.Templates.MvcModule; using Volo.Abp.Cli.ProjectBuilding.Templates.Wpf; using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.Cli.ProjectBuilding { public class TemplateInfoProvider : ITemplateInfoProvider, ITransientDependency { - public TemplateInfo GetDefault() + public ILogger Logger { get; set; } + + public ICancellationTokenProvider CancellationTokenProvider { get; } + public IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } + public AuthService AuthService { get; } + + public TemplateInfoProvider(ICancellationTokenProvider cancellationTokenProvider, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler, + AuthService authService) { - return Get(AppTemplate.TemplateName); + CancellationTokenProvider = cancellationTokenProvider; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; + AuthService = authService; + + Logger = NullLogger.Instance; + } + + public async Task GetDefaultAsync() + { + var defaultTemplateName = await CheckProLicenseAsync() ? AppProTemplate.TemplateName : AppTemplate.TemplateName; + + return Get(defaultTemplateName); } public TemplateInfo Get(string name) @@ -35,5 +61,36 @@ namespace Volo.Abp.Cli.ProjectBuilding throw new Exception("There is no template found with given name: " + name); } } + + + private async Task CheckProLicenseAsync() + { + if (!AuthService.IsLoggedIn()) + { + return false; + } + + var url = $"{CliUrls.WwwAbpIo}api/license/check-user"; + + using (var client = new CliHttpClient()) + { + var response = await client.GetHttpResponseMessageWithRetryAsync( + url, + CancellationTokenProvider.Token, + Logger); + + if (!response.IsSuccessStatusCode) + { + throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); + } + + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + + var responseContent = await response.Content.ReadAsStringAsync(); + var result = JsonSerializer.Deserialize(responseContent); + + return result; + } + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs index 02b26eba39..cbbb094d11 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs @@ -49,7 +49,7 @@ namespace Volo.Abp.Cli.ProjectBuilding public async Task BuildAsync(ProjectBuildArgs args) { - var templateInfo = GetTemplateInfo(args); + var templateInfo = await GetTemplateInfoAsync(args); NormalizeArgs(args, templateInfo); @@ -175,11 +175,11 @@ namespace Volo.Abp.Cli.ProjectBuilding } } - private TemplateInfo GetTemplateInfo(ProjectBuildArgs args) + private async Task GetTemplateInfoAsync(ProjectBuildArgs args) { if (args.TemplateName.IsNullOrWhiteSpace()) { - return TemplateInfoProvider.GetDefault(); + return await TemplateInfoProvider.GetDefaultAsync(); } else { From c45dc236c341c41152cc7e3047d25db35bf8e22b Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Fri, 4 Dec 2020 10:00:44 +0300 Subject: [PATCH 2/6] cli TemplateInfoProvider added try-catch --- .../ProjectBuilding/TemplateInfoProvider.cs | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs index 269795d4a4..b69e898068 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateInfoProvider.cs @@ -70,26 +70,33 @@ namespace Volo.Abp.Cli.ProjectBuilding return false; } - var url = $"{CliUrls.WwwAbpIo}api/license/check-user"; - - using (var client = new CliHttpClient()) + try { - var response = await client.GetHttpResponseMessageWithRetryAsync( - url, - CancellationTokenProvider.Token, - Logger); + var url = $"{CliUrls.WwwAbpIo}api/license/check-user"; - if (!response.IsSuccessStatusCode) + using (var client = new CliHttpClient()) { - throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); - } + var response = await client.GetHttpResponseMessageWithRetryAsync( + url, + CancellationTokenProvider.Token, + Logger); - await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + if (!response.IsSuccessStatusCode) + { + throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); + } - var responseContent = await response.Content.ReadAsStringAsync(); - var result = JsonSerializer.Deserialize(responseContent); + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); - return result; + var responseContent = await response.Content.ReadAsStringAsync(); + var result = JsonSerializer.Deserialize(responseContent); + + return result; + } + } + catch (Exception) + { + return false; } } } From 68365f9a46ef3118f207b02e89295a3f3614f765 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 7 Dec 2020 13:43:55 +0800 Subject: [PATCH 3/6] Localize exception messages in AbpFeaturesModule. Resolve #1119 --- .../DefaultExceptionToErrorInfoConverter.cs | 6 -- .../Volo.Abp.Features.csproj | 7 ++- .../Volo/Abp/Features/AbpFeatureErrorCodes.cs | 11 ++++ .../Volo/Abp/Features/AbpFeaturesModule.cs | 22 ++++++- .../Abp/Features/FeatureCheckerExtensions.cs | 23 ++++--- .../Localization/AbpFeatureResource.cs | 10 ++++ .../Volo/Abp/Features/Localization/en.json | 8 +++ .../Volo/Abp/Features/Localization/tr.json | 8 +++ .../Abp/Features/Localization/zh-Hans.json | 8 +++ .../AbpAuthorizationException.cs | 29 ++++++++- .../Volo.Abp.Features.Tests.csproj | 1 + .../Abp/Features/AbpFeaturesTestModule.cs | 4 +- .../FeatureCheckerExtensions_Tests.cs | 60 +++++++++++++++++++ 13 files changed, 173 insertions(+), 24 deletions(-) create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeatureErrorCodes.cs create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/AbpFeatureResource.cs create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/en.json create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/tr.json create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/zh-Hans.json create mode 100644 framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs 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.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..a3ea2cc710 --- /dev/null +++ b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs @@ -0,0 +1,60 @@ +using System.Threading.Tasks; +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 IFeatureChecker _featureChecker; + private readonly IExceptionToErrorInfoConverter _exceptionToErrorInfoConverter; + + public FeatureCheckerExtensions_Tests() + { + _featureChecker = GetRequiredService(); + _exceptionToErrorInfoConverter = GetRequiredService(); + } + + [Fact] + public async Task CheckEnabledAsync() + { + using (CultureHelper.Use("zh-Hans")) + { + var ex = await Assert.ThrowsAsync(async () => + await _featureChecker.CheckEnabledAsync("BooleanTestFeature1")); + + var errorInfo = _exceptionToErrorInfoConverter.Convert(ex, false); + errorInfo.Message.ShouldBe("功能未启用: BooleanTestFeature1"); + } + } + + [Fact] + public async Task CheckEnabled_RequiresAll() + { + using (CultureHelper.Use("zh-Hans")) + { + var ex = await Assert.ThrowsAsync(async () => + await _featureChecker.CheckEnabledAsync(true, "BooleanTestFeature1", "BooleanTestFeature2")); + + var errorInfo = _exceptionToErrorInfoConverter.Convert(ex, false); + errorInfo.Message.ShouldBe("必要的功能未启用. 这些功能需要启用: BooleanTestFeature1, BooleanTestFeature2"); + } + } + + [Fact] + public async Task CheckEnabled_Not_RequiresAll() + { + using (CultureHelper.Use("zh-Hans")) + { + var ex = await Assert.ThrowsAsync(async () => + await _featureChecker.CheckEnabledAsync(false, "BooleanTestFeature1", "BooleanTestFeature2")); + + var errorInfo = _exceptionToErrorInfoConverter.Convert(ex, false); + errorInfo.Message.ShouldBe("必要的功能未启用. 需要启用这些功能中的一项:BooleanTestFeature1, BooleanTestFeature2"); + } + } + } +} From f168fd27ca8eb5a8569eec3696ef2dc211d1af8c Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 7 Dec 2020 15:06:46 +0800 Subject: [PATCH 4/6] Localize exception messages in AbpAuthorizationModule.. --- .../AbpAuthorizationServiceExtensions.cs | 19 ++++--- .../Volo.Abp.Authorization.csproj | 7 ++- .../AbpAuthorizationErrorCodes.cs | 15 ++++++ .../Authorization/AbpAuthorizationModule.cs | 20 +++++++ .../Localization/AbpAuthorizationResource.cs | 10 ++++ .../Abp/Authorization/Localization/en.json | 10 ++++ .../Abp/Authorization/Localization/tr.json | 10 ++++ .../Authorization/Localization/zh-Hans.json | 10 ++++ ...AbpAuthorizationServiceExtensions_Tests.cs | 49 +++++++++++++++++ .../Volo.Abp.Authorization.Tests.csproj | 1 + .../AbpAuthorizationTestModule.cs | 4 +- .../FeatureCheckerExtensions_Tests.cs | 52 ++++++------------- 12 files changed, 162 insertions(+), 45 deletions(-) create mode 100644 framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationErrorCodes.cs create mode 100644 framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/AbpAuthorizationResource.cs create mode 100644 framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/en.json create mode 100644 framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/tr.json create mode 100644 framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/zh-Hans.json create mode 100644 framework/test/Volo.Abp.Authorization.Tests/Microsoft/AspNetCore/Authorization/AbpAuthorizationServiceExtensions_Tests.cs 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..e980f9df99 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs @@ -3,11 +3,14 @@ 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 { @@ -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/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/FeatureCheckerExtensions_Tests.cs b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureCheckerExtensions_Tests.cs index a3ea2cc710..0df9548f3c 100644 --- 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 @@ -1,5 +1,4 @@ -using System.Threading.Tasks; -using Shouldly; +using Shouldly; using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.Authorization; using Volo.Abp.Localization; @@ -9,51 +8,32 @@ namespace Volo.Abp.Features { public class FeatureCheckerExtensions_Tests : FeatureTestBase { - private readonly IFeatureChecker _featureChecker; private readonly IExceptionToErrorInfoConverter _exceptionToErrorInfoConverter; public FeatureCheckerExtensions_Tests() { - _featureChecker = GetRequiredService(); _exceptionToErrorInfoConverter = GetRequiredService(); } [Fact] - public async Task CheckEnabledAsync() + public void Test_AbpAuthorizationException_Localization() { using (CultureHelper.Use("zh-Hans")) { - var ex = await Assert.ThrowsAsync(async () => - await _featureChecker.CheckEnabledAsync("BooleanTestFeature1")); - - var errorInfo = _exceptionToErrorInfoConverter.Convert(ex, false); - errorInfo.Message.ShouldBe("功能未启用: BooleanTestFeature1"); - } - } - - [Fact] - public async Task CheckEnabled_RequiresAll() - { - using (CultureHelper.Use("zh-Hans")) - { - var ex = await Assert.ThrowsAsync(async () => - await _featureChecker.CheckEnabledAsync(true, "BooleanTestFeature1", "BooleanTestFeature2")); - - var errorInfo = _exceptionToErrorInfoConverter.Convert(ex, false); - errorInfo.Message.ShouldBe("必要的功能未启用. 这些功能需要启用: BooleanTestFeature1, BooleanTestFeature2"); - } - } - - [Fact] - public async Task CheckEnabled_Not_RequiresAll() - { - using (CultureHelper.Use("zh-Hans")) - { - var ex = await Assert.ThrowsAsync(async () => - await _featureChecker.CheckEnabledAsync(false, "BooleanTestFeature1", "BooleanTestFeature2")); - - var errorInfo = _exceptionToErrorInfoConverter.Convert(ex, false); - errorInfo.Message.ShouldBe("必要的功能未启用. 需要启用这些功能中的一项:BooleanTestFeature1, BooleanTestFeature2"); + 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"); } } } From 8b3c8b1660e1d64c01287c38a8d6865261ea9372 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 7 Dec 2020 15:10:55 +0800 Subject: [PATCH 5/6] Depend on AbpLocalizationModule instead of AbpLocalizationAbstractionsModule. --- .../Volo/Abp/Authorization/AbpAuthorizationModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e980f9df99..b4d5795b9c 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.Authorization { [DependsOn( typeof(AbpSecurityModule), - typeof(AbpLocalizationAbstractionsModule), + typeof(AbpLocalizationModule), typeof(AbpMultiTenancyModule) )] public class AbpAuthorizationModule : AbpModule From 51d0d219d05a19a8ed7181aa9034217883d9947b Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 7 Dec 2020 15:53:19 +0800 Subject: [PATCH 6/6] Support sub-application deployment --- .../Themes/Basic/Branding.razor | 2 +- .../AbpIdentityWebMainMenuContributor.cs | 4 ++-- .../Menus/SettingManagementMenuContributor.cs | 2 +- .../Navigation/TenantManagementBlazorMenuContributor.cs | 2 +- .../Menus/MyProjectNameMenuContributor.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor index 4810320664..ac629423ce 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor @@ -1,3 +1,3 @@ @using Volo.Abp.Ui.Branding @inject IBrandingProvider BrandingProvider -@BrandingProvider.AppName +@BrandingProvider.AppName diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs index 3198e1335d..5e5714a851 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs @@ -27,12 +27,12 @@ namespace Volo.Abp.Identity.Blazor if (hasRolePermission) { - identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Roles, l["Roles"], url: "/identity/roles")); + identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Roles, l["Roles"], url: "identity/roles")); } if (hasUserPermission) { - identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Users, l["Users"], url: "/identity/users")); + identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Users, l["Users"], url: "identity/users")); } } } diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Menus/SettingManagementMenuContributor.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Menus/SettingManagementMenuContributor.cs index 44343e0498..531613b77c 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Menus/SettingManagementMenuContributor.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Menus/SettingManagementMenuContributor.cs @@ -37,7 +37,7 @@ namespace Volo.Abp.SettingManagement.Blazor.Menus new ApplicationMenuItem( SettingManagementMenus.GroupName, l["Settings"], - "/setting-management", + "setting-management", icon: "fa fa-cog" ) ); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs index c1d6e9ac7a..03bfd6b2d2 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Navigation/TenantManagementBlazorMenuContributor.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.TenantManagement.Blazor.Navigation if (await context.IsGrantedAsync(TenantManagementPermissions.Tenants.Default)) { - tenantManagementMenuItem.AddItem(new ApplicationMenuItem(TenantManagementMenuNames.Tenants, l["Tenants"], url: "/tenant-management/tenants")); + tenantManagementMenuItem.AddItem(new ApplicationMenuItem(TenantManagementMenuNames.Tenants, l["Tenants"], url: "tenant-management/tenants")); } } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Menus/MyProjectNameMenuContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Menus/MyProjectNameMenuContributor.cs index 8b5aebacce..7f8964d6cd 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Menus/MyProjectNameMenuContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Menus/MyProjectNameMenuContributor.cs @@ -39,7 +39,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Menus new ApplicationMenuItem( MyProjectNameMenus.Home, l["Menu:Home"], - "/", + "", icon: "fas fa-home" ) );