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/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.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..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
@@ -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)
+ {
+ CancellationTokenProvider = cancellationTokenProvider;
+ RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
+ AuthService = authService;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public async Task GetDefaultAsync()
{
- return Get(AppTemplate.TemplateName);
+ var defaultTemplateName = await CheckProLicenseAsync() ? AppProTemplate.TemplateName : AppTemplate.TemplateName;
+
+ return Get(defaultTemplateName);
}
public TemplateInfo Get(string name)
@@ -35,5 +61,43 @@ 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;
+ }
+
+ try
+ {
+ 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;
+ }
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
}
}
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
{
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");
+ }
+ }
+ }
+}
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"
)
);