diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs index 84d0ad0b2c5..aebd14f36e1 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs @@ -13,19 +13,31 @@ public class PermissionValueProviderManager : IPermissionValueProviderManager, I private readonly Lazy> _lazyProviders; protected AbpPermissionOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } public PermissionValueProviderManager( IServiceProvider serviceProvider, IOptions options) { Options = options.Value; + ServiceProvider = serviceProvider; - _lazyProviders = new Lazy>( - () => Options - .ValueProviders - .Select(c => serviceProvider.GetRequiredService(c) as IPermissionValueProvider) - .ToList()!, - true - ); + _lazyProviders = new Lazy>(GetProviders, true); + } + + protected virtual List GetProviders() + { + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as IPermissionValueProvider)!) + .ToList(); + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate permission value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } + + return providers; } } diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs index c2a4a71ab39..66e145563dc 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs @@ -12,34 +12,26 @@ public class FeatureChecker : FeatureCheckerBase protected AbpFeatureOptions Options { get; } protected IServiceProvider ServiceProvider { get; } protected IFeatureDefinitionManager FeatureDefinitionManager { get; } - protected List Providers => _providers.Value; - - private readonly Lazy> _providers; + protected IFeatureValueProviderManager FeatureValueProviderManager { get; } public FeatureChecker( IOptions options, IServiceProvider serviceProvider, - IFeatureDefinitionManager featureDefinitionManager) + IFeatureDefinitionManager featureDefinitionManager, + IFeatureValueProviderManager featureValueProviderManager) { ServiceProvider = serviceProvider; FeatureDefinitionManager = featureDefinitionManager; + FeatureValueProviderManager = featureValueProviderManager; Options = options.Value; - - _providers = new Lazy>( - () => Options - .ValueProviders - .Select(type => (ServiceProvider.GetRequiredService(type) as IFeatureValueProvider)!) - .ToList(), - true - ); } public override async Task GetOrNullAsync(string name) { var featureDefinition = await FeatureDefinitionManager.GetAsync(name); - var providers = Enumerable - .Reverse(Providers); + var providers = FeatureValueProviderManager.ValueProviders + .Reverse(); if (featureDefinition.AllowedProviders.Any()) { diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs new file mode 100644 index 00000000000..c793ee8ce5b --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +public class FeatureValueProviderManager : IFeatureValueProviderManager, ISingletonDependency +{ + public IReadOnlyList ValueProviders => _lazyProviders.Value; + private readonly Lazy> _lazyProviders; + + protected AbpFeatureOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } + + public FeatureValueProviderManager( + IServiceProvider serviceProvider, + IOptions options) + { + Options = options.Value; + ServiceProvider = serviceProvider; + + _lazyProviders = new Lazy>(GetProviders, true); + } + + protected virtual List GetProviders() + { + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as IFeatureValueProvider)!) + .ToList(); + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate feature value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } + + return providers; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs new file mode 100644 index 00000000000..56de662a991 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Volo.Abp.Features; + +public interface IFeatureValueProviderManager +{ + IReadOnlyList ValueProviders { get; } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs index d0300357dce..116fae56438 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs @@ -10,7 +10,9 @@ namespace Volo.Abp.Settings; public class SettingValueProviderManager : ISettingValueProviderManager, ISingletonDependency { public List Providers => _lazyProviders.Value; + protected AbpSettingOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } private readonly Lazy> _lazyProviders; public SettingValueProviderManager( @@ -19,13 +21,24 @@ public SettingValueProviderManager( { Options = options.Value; + ServiceProvider = serviceProvider; + + _lazyProviders = new Lazy>(GetProviders, true); + } + + protected virtual List GetProviders() + { + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as ISettingValueProvider)!) + .ToList(); + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate setting value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } - _lazyProviders = new Lazy>( - () => Options - .ValueProviders - .Select(type => serviceProvider.GetRequiredService(type) as ISettingValueProvider) - .ToList()!, - true - ); + return providers; } } diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs new file mode 100644 index 00000000000..d4af25ad3a6 --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs @@ -0,0 +1,59 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Authorization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Authorization.TestServices; +using Xunit; + +namespace Volo.Abp; + +public class PermissionValueProviderManager_Tests: AuthorizationTestBase +{ + private readonly IPermissionValueProviderManager _permissionValueProviderManager; + + public PermissionValueProviderManager_Tests() + { + _permissionValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.Services.Configure(permissionOptions => + { + permissionOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _permissionValueProviderManager.ValueProviders; + }); + + exception.Message.ShouldBe($"Duplicate permission value provider name detected: TestPermissionValueProvider1. Providers:{Environment.NewLine}{typeof(TestDuplicatePermissionValueProvider).FullName}{Environment.NewLine}{typeof(TestPermissionValueProvider1).FullName}"); + } +} + +public class TestDuplicatePermissionValueProvider : PermissionValueProvider +{ + public TestDuplicatePermissionValueProvider(IPermissionStore permissionStore) : base(permissionStore) + { + } + + public override string Name => "TestPermissionValueProvider1"; + + public override Task CheckAsync(PermissionValueCheckContext context) + { + throw new NotImplementedException(); + } + + public override Task CheckAsync(PermissionValuesCheckContext context) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs new file mode 100644 index 00000000000..7e73ef65fce --- /dev/null +++ b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Features; + +public class FeatureValueProviderManager_Tests : FeatureTestBase +{ + private readonly IFeatureValueProviderManager _featureValueProviderManager; + + public FeatureValueProviderManager_Tests() + { + _featureValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.Services.Configure(permissionOptions => + { + permissionOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _featureValueProviderManager.ValueProviders; + }); + + exception.Message.ShouldBe($"Duplicate feature value provider name detected: {TestDuplicateFeatureValueProvider.ProviderName}. Providers:{Environment.NewLine}{typeof(TestDuplicateFeatureValueProvider).FullName}{Environment.NewLine}{typeof(DefaultValueFeatureValueProvider).FullName}"); + } +} + +public class TestDuplicateFeatureValueProvider : FeatureValueProvider +{ + public const string ProviderName = "D"; + + public override string Name => ProviderName; + + public TestDuplicateFeatureValueProvider(IFeatureStore settingStore) + : base(settingStore) + { + + } + + public override Task GetOrNullAsync(FeatureDefinition setting) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs new file mode 100644 index 00000000000..f85e465d8ef --- /dev/null +++ b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.Settings; + +public class SettingValueProviderManager_Tests: AbpIntegratedTest +{ + private readonly ISettingValueProviderManager _settingValueProviderManager; + + public SettingValueProviderManager_Tests() + { + _settingValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + options.Services.Configure(settingOptions => + { + settingOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _settingValueProviderManager.Providers; + }); + + exception.Message.ShouldBe($"Duplicate setting value provider name detected: {TestDuplicateSettingValueProvider.ProviderName}. Providers:{Environment.NewLine}{typeof(TestDuplicateSettingValueProvider).FullName}{Environment.NewLine}{typeof(TestSettingValueProvider).FullName}"); + } +} + +public class TestDuplicateSettingValueProvider : ISettingValueProvider, ITransientDependency +{ + public const string ProviderName = "Test"; + + + public string Name => ProviderName; + + public TestDuplicateSettingValueProvider() + { + } + + public Task GetOrNullAsync(SettingDefinition setting) + { + throw new NotImplementedException(); + } + + public Task> GetAllAsync(SettingDefinition[] settings) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs index 1a5356a1bea..9805f03752c 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs @@ -144,7 +144,7 @@ public virtual async Task SetAsync( if (!providers.Any()) { - return; + throw new AbpException($"Unknown feature value provider: {providerName}"); } if (providers.Count > 1 && !forceToSet && value != null) diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs index 831d021e38f..fd4ea324ea4 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs @@ -209,4 +209,15 @@ public async Task DeleteAsync() (await _featureManager.GetOrNullAsync(TestFeatureDefinitionProvider.BackupCount, TenantFeatureValueProvider.ProviderName, TestEditionIds.TenantId.ToString())).ShouldBe("0"); } + + [Fact] + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _featureManager.SetAsync(TestFeatureDefinitionProvider.EmailSupport, "true", "UndefinedProvider", "Test"); + }); + + exception.Message.ShouldBe("Unknown feature value provider: UndefinedProvider"); + } } diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs index 1f771bdb3ba..3f2e9c7565f 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs @@ -134,6 +134,21 @@ await _permissionManager.SetAsync( "Test", true); } + + [Fact] + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _permissionManager.SetAsync( + "MyPermission1", + "UndefinedProvider", + "Test", + true); + }); + + exception.Message.ShouldBe("Unknown permission management provider: UndefinedProvider"); + } [Fact] public async Task UpdateProviderKey() diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs index 5439c1213a2..ddf451154db 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs @@ -125,7 +125,7 @@ public virtual async Task SetAsync(string name, string value, string providerNam if (!providers.Any()) { - return; + throw new AbpException($"Unknown setting value provider: {providerName}"); } if (setting.IsEncrypted) diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs index 44655c8cb0a..ca9db64c703 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Settings; @@ -63,4 +64,15 @@ public async Task Should_Set_Global_Value() (await _settingManager.GetOrNullGlobalAsync("MySetting1")).ShouldBe("43"); (await _settingProvider.GetOrNullAsync("MySetting1")).ShouldBe("43"); } + + [Fact] + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _settingManager.SetAsync("MySetting1", "43", "UndefinedProvider", "Test"); + }); + + exception.Message.ShouldBe("Unknown setting value provider: UndefinedProvider"); + } } \ No newline at end of file