diff --git a/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleResourcePermissionProviderKeyLookupService.cs b/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleResourcePermissionProviderKeyLookupService.cs index ab1824e13d..d305889e4e 100644 --- a/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleResourcePermissionProviderKeyLookupService.cs +++ b/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleResourcePermissionProviderKeyLookupService.cs @@ -24,6 +24,11 @@ public class RoleResourcePermissionProviderKeyLookupService : IResourcePermissio DisplayName = LocalizableString.Create(nameof(RoleResourcePermissionProviderKeyLookupService)); } + public virtual Task IsAvailableAsync() + { + return Task.FromResult(true); + } + public virtual async Task> SearchAsync(string filter = null, int page = 1, CancellationToken cancellationToken = default) { var roles = await UserRoleFinder.SearchRoleAsync(filter, page); diff --git a/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/UserResourcePermissionProviderKeyLookupService.cs b/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/UserResourcePermissionProviderKeyLookupService.cs index 83f0e79099..3fd5cd0643 100644 --- a/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/UserResourcePermissionProviderKeyLookupService.cs +++ b/modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/UserResourcePermissionProviderKeyLookupService.cs @@ -25,6 +25,11 @@ public class UserResourcePermissionProviderKeyLookupService : IResourcePermissio DisplayName = LocalizableString.Create(nameof(UserResourcePermissionProviderKeyLookupService)); } + public virtual Task IsAvailableAsync() + { + return Task.FromResult(true); + } + public virtual async Task> SearchAsync(string filter = null, int page = 1, CancellationToken cancellationToken = default) { var users = await UserRoleFinder.SearchUserAsync(filter, page); diff --git a/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/ClientResourcePermissionManagementProvider.cs b/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/ClientResourcePermissionManagementProvider.cs index 9285742131..cca3333d22 100644 --- a/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/ClientResourcePermissionManagementProvider.cs +++ b/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/ClientResourcePermissionManagementProvider.cs @@ -20,6 +20,11 @@ public class ClientResourcePermissionManagementProvider : ResourcePermissionMana { } + public override Task IsAvailableAsync() + { + return Task.FromResult(CurrentTenant.Id == null); + } + public override Task CheckAsync(string name, string resourceName, string resourceKey, string providerName, string providerKey) { using (CurrentTenant.Change(null)) diff --git a/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/ClientResourcePermissionProviderKeyLookupService.cs b/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/ClientResourcePermissionProviderKeyLookupService.cs index 7fc813dabb..8c3df13c4c 100644 --- a/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/ClientResourcePermissionProviderKeyLookupService.cs +++ b/modules/identityserver/src/Volo.Abp.PermissionManagement.Domain.IdentityServer/Volo/Abp/PermissionManagement/IdentityServer/ClientResourcePermissionProviderKeyLookupService.cs @@ -8,6 +8,7 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.Localization; using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; namespace Volo.Abp.PermissionManagement.IdentityServer; @@ -19,12 +20,22 @@ public class ClientResourcePermissionProviderKeyLookupService : IResourcePermiss protected IClientFinder ClientFinder { get; } - public ClientResourcePermissionProviderKeyLookupService(IClientFinder clientFinder) + protected ICurrentTenant CurrentTenant { get; } + + public ClientResourcePermissionProviderKeyLookupService( + IClientFinder clientFinder, + ICurrentTenant currentTenant) { ClientFinder = clientFinder; + CurrentTenant = currentTenant; DisplayName = LocalizableString.Create(nameof(ClientResourcePermissionProviderKeyLookupService)); } + public virtual Task IsAvailableAsync() + { + return Task.FromResult(CurrentTenant.Id == null); + } + public virtual async Task> SearchAsync(string filter = null, int page = 1, CancellationToken cancellationToken = default) { var clients = await ClientFinder.SearchAsync(filter, page); diff --git a/modules/openiddict/src/Volo.Abp.PermissionManagement.Domain.OpenIddict/Volo/Abp/PermissionManagement/OpenIddict/ApplicationResourcePermissionManagementProvider.cs b/modules/openiddict/src/Volo.Abp.PermissionManagement.Domain.OpenIddict/Volo/Abp/PermissionManagement/OpenIddict/ApplicationResourcePermissionManagementProvider.cs index e12fa63d03..4f2094c24c 100644 --- a/modules/openiddict/src/Volo.Abp.PermissionManagement.Domain.OpenIddict/Volo/Abp/PermissionManagement/OpenIddict/ApplicationResourcePermissionManagementProvider.cs +++ b/modules/openiddict/src/Volo.Abp.PermissionManagement.Domain.OpenIddict/Volo/Abp/PermissionManagement/OpenIddict/ApplicationResourcePermissionManagementProvider.cs @@ -17,6 +17,11 @@ public class ApplicationResourcePermissionManagementProvider : ResourcePermissio { } + public override Task IsAvailableAsync() + { + return Task.FromResult(CurrentTenant.Id == null); + } + public override Task CheckAsync(string name, string resourceName, string resourceKey, string providerName, string providerKey) { using (CurrentTenant.Change(null)) diff --git a/modules/openiddict/src/Volo.Abp.PermissionManagement.Domain.OpenIddict/Volo/Abp/PermissionManagement/OpenIddict/ApplicationResourcePermissionProviderKeyLookupService.cs b/modules/openiddict/src/Volo.Abp.PermissionManagement.Domain.OpenIddict/Volo/Abp/PermissionManagement/OpenIddict/ApplicationResourcePermissionProviderKeyLookupService.cs index 1423ca9768..31e42ffcd5 100644 --- a/modules/openiddict/src/Volo.Abp.PermissionManagement.Domain.OpenIddict/Volo/Abp/PermissionManagement/OpenIddict/ApplicationResourcePermissionProviderKeyLookupService.cs +++ b/modules/openiddict/src/Volo.Abp.PermissionManagement.Domain.OpenIddict/Volo/Abp/PermissionManagement/OpenIddict/ApplicationResourcePermissionProviderKeyLookupService.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Volo.Abp.Authorization.Permissions.Resources; using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; using Volo.Abp.OpenIddict.Applications; using Volo.Abp.OpenIddict.Localization; @@ -19,12 +20,22 @@ public class ApplicationResourcePermissionProviderKeyLookupService : IResourcePe protected IApplicationFinder ApplicationFinder { get; } - public ApplicationResourcePermissionProviderKeyLookupService(IApplicationFinder applicationFinder) + protected ICurrentTenant CurrentTenant { get; } + + public ApplicationResourcePermissionProviderKeyLookupService( + IApplicationFinder applicationFinder, + ICurrentTenant currentTenant) { ApplicationFinder = applicationFinder; + CurrentTenant = currentTenant; DisplayName = LocalizableString.Create(nameof(ApplicationResourcePermissionProviderKeyLookupService)); } + public virtual Task IsAvailableAsync() + { + return Task.FromResult(CurrentTenant.Id == null); + } + public virtual async Task> SearchAsync(string filter = null, int page = 1, CancellationToken cancellationToken = default) { var applications = await ApplicationFinder.SearchAsync(filter, page); diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionManagementProvider.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionManagementProvider.cs index 429e6f6e85..92850c3420 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionManagementProvider.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionManagementProvider.cs @@ -8,6 +8,8 @@ public interface IResourcePermissionManagementProvider : ISingletonDependency // { string Name { get; } + Task IsAvailableAsync(); + Task CheckAsync( [NotNull] string name, [NotNull] string resourceName, diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionProviderKeyLookupService.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionProviderKeyLookupService.cs index aa6ad2a06e..3efdb37401 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionProviderKeyLookupService.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionProviderKeyLookupService.cs @@ -9,6 +9,8 @@ public interface IResourcePermissionProviderKeyLookupService { public string Name { get; } + Task IsAvailableAsync(); + public ILocalizableString DisplayName { get; } Task> SearchAsync(string filter = null, int page = 1, CancellationToken cancellationToken = default); diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManagementProvider.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManagementProvider.cs index 9682965c67..c579307c86 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManagementProvider.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManagementProvider.cs @@ -26,6 +26,11 @@ public abstract class ResourcePermissionManagementProvider : IResourcePermission CurrentTenant = currentTenant; } + public virtual Task IsAvailableAsync() + { + return Task.FromResult(true); + } + public virtual async Task CheckAsync(string name, string resourceName, string resourceKey, string providerName, string providerKey) { var multiplePermissionValueProviderGrantInfo = await CheckAsync(new[] { name }, resourceName, resourceKey, providerName, providerKey); diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs index c4b898e761..f951f312eb 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs @@ -70,9 +70,17 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD ); } - public virtual Task> GetProviderKeyLookupServicesAsync() + public virtual async Task> GetProviderKeyLookupServicesAsync() { - return Task.FromResult(_lazyProviderKeyLookupServices.Value); + var availableServices = new List(); + foreach (var service in _lazyProviderKeyLookupServices.Value) + { + if (await service.IsAvailableAsync()) + { + availableServices.Add(service); + } + } + return availableServices; } public virtual Task GetProviderKeyLookupServiceAsync(string serviceName) @@ -282,6 +290,12 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD throw new AbpException("Unknown resource permission management provider: " + providerName); } + if (!await provider.IsAvailableAsync()) + { + //TODO: BusinessException + throw new AbpException($"The resource permission management provider '{providerName}' is not available in the current context."); + } + await provider.SetAsync(permissionName, resourceName, resourceKey, providerKey, isGranted); } @@ -378,6 +392,11 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD foreach (var provider in ManagementProviders) { + if (!await provider.IsAvailableAsync()) + { + continue; + } + permissionNames = resourcePermissions.Select(x => x.Name).ToArray(); var multiplePermissionValueProviderGrantInfo = await provider.CheckAsync(permissionNames, resourceName, resourceKey, providerName, providerKey); diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/ResourcePermissionManager_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/ResourcePermissionManager_Tests.cs index 73d37a5ff3..4124f216cd 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/ResourcePermissionManager_Tests.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/ResourcePermissionManager_Tests.cs @@ -334,4 +334,55 @@ public class ResourcePermissionManager_Tests : PermissionTestBase "Test", "Test")).ShouldBeNull(); } + + [Fact] + public async Task GetProviderKeyLookupServicesAsync_Should_Not_Return_Unavailable_Services() + { + var lookupServices = await _resourcePermissionManager.GetProviderKeyLookupServicesAsync(); + + lookupServices.ShouldContain(s => s.Name == "Test"); + lookupServices.ShouldNotContain(s => s.Name == "TestUnavailable"); + } + + [Fact] + public async Task GetAsync_Should_Not_Return_Grant_From_Unavailable_Provider() + { + // Insert a grant directly via repository to simulate data stored by an unavailable provider + await _resourcePermissionGrantRepository.InsertAsync(new ResourcePermissionGrant( + Guid.NewGuid(), + "MyResourcePermission1", + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1, + "TestUnavailable", + "someKey") + ); + + var grantedProviders = await _resourcePermissionManager.GetAsync( + "MyResourcePermission1", + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1, + "TestUnavailable", + "someKey"); + + // The unavailable provider is skipped, so the permission should not be considered granted via it + grantedProviders.IsGranted.ShouldBeFalse(); + grantedProviders.Providers.ShouldNotContain(p => p.Name == "TestUnavailable"); + } + + [Fact] + public async Task SetAsync_Should_Throw_When_Provider_Is_Unavailable() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _resourcePermissionManager.SetAsync( + "MyResourcePermission1", + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1, + "TestUnavailable", + "someKey", + true); + }); + + exception.Message.ShouldBe("The resource permission management provider 'TestUnavailable' is not available in the current context."); + } } diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs index bf6eca7bc2..0372fa41d6 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs @@ -23,7 +23,9 @@ public class AbpPermissionManagementTestBaseModule : AbpModule { options.ManagementProviders.Add(); options.ResourceManagementProviders.Add(); + options.ResourceManagementProviders.Add(); options.ResourcePermissionProviderKeyLookupServices.Add(); + options.ResourcePermissionProviderKeyLookupServices.Add(); }); } diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestResourcePermissionProviderKeyLookupService.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestResourcePermissionProviderKeyLookupService.cs index f42a204f7a..29a4589ac6 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestResourcePermissionProviderKeyLookupService.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestResourcePermissionProviderKeyLookupService.cs @@ -12,6 +12,11 @@ public class TestResourcePermissionProviderKeyLookupService : IResourcePermissio public ILocalizableString DisplayName => new LocalizableString("Test", "TestResource"); + public Task IsAvailableAsync() + { + return Task.FromResult(true); + } + public Task> SearchAsync(string filter = null, int page = 1, CancellationToken cancellationToken = default) { throw new System.NotImplementedException(); diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestUnavailableResourcePermissionManagementProvider.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestUnavailableResourcePermissionManagementProvider.cs new file mode 100644 index 0000000000..6cbd3c4c40 --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestUnavailableResourcePermissionManagementProvider.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Volo.Abp.Guids; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.PermissionManagement; + +public class TestUnavailableResourcePermissionManagementProvider : ResourcePermissionManagementProvider +{ + public override string Name => "TestUnavailable"; + + public TestUnavailableResourcePermissionManagementProvider( + IResourcePermissionGrantRepository resourcePermissionGrantRepository, + IGuidGenerator guidGenerator, + ICurrentTenant currentTenant) + : base( + resourcePermissionGrantRepository, + guidGenerator, + currentTenant) + { + } + + public override Task IsAvailableAsync() + { + return Task.FromResult(false); + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestUnavailableResourcePermissionProviderKeyLookupService.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestUnavailableResourcePermissionProviderKeyLookupService.cs new file mode 100644 index 0000000000..dd273d614c --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestUnavailableResourcePermissionProviderKeyLookupService.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization; + +namespace Volo.Abp.PermissionManagement; + +public class TestUnavailableResourcePermissionProviderKeyLookupService : IResourcePermissionProviderKeyLookupService, ITransientDependency +{ + public string Name => "TestUnavailable"; + + public ILocalizableString DisplayName => new LocalizableString("TestUnavailable", "TestResource"); + + public Task IsAvailableAsync() + { + return Task.FromResult(false); + } + + public Task> SearchAsync(string filter = null, int page = 1, CancellationToken cancellationToken = default) + { + throw new System.NotImplementedException(); + } + + public Task> SearchAsync(string[] keys, CancellationToken cancellationToken = default) + { + throw new System.NotImplementedException(); + } +}