diff --git a/docs/en/modules/permission-management.md b/docs/en/modules/permission-management.md index 103bd4ff7f..5a80648ecb 100644 --- a/docs/en/modules/permission-management.md +++ b/docs/en/modules/permission-management.md @@ -346,6 +346,51 @@ Configure(options => }); ```` +#### Controlling Provider Availability + +You can control whether a provider is active in a given context by overriding `IsAvailableAsync()`. When a provider returns `false`, it is completely excluded from all read, write, and UI listing operations. This is useful for host-only providers that should not be visible or writable in a tenant context. + +````csharp +public class CustomResourcePermissionManagementProvider + : ResourcePermissionManagementProvider +{ + public override string Name => "Custom"; + + // ...constructor... + + public override Task IsAvailableAsync() + { + // Only available for the host, not for tenants + return Task.FromResult(CurrentTenant.Id == null); + } +} +```` + +The same `IsAvailableAsync()` method is available on `IResourcePermissionProviderKeyLookupService`, which controls whether the provider appears in the UI provider picker: + +````csharp +public class CustomResourcePermissionProviderKeyLookupService + : IResourcePermissionProviderKeyLookupService, ITransientDependency +{ + public string Name => "Custom"; + public ILocalizableString DisplayName { get; } + + protected ICurrentTenant CurrentTenant { get; } + + public CustomResourcePermissionProviderKeyLookupService(ICurrentTenant currentTenant) + { + CurrentTenant = currentTenant; + } + + public Task IsAvailableAsync() + { + return Task.FromResult(CurrentTenant.Id == null); + } + + // ...SearchAsync implementations... +} +```` + ## Permission Value Providers Permission value providers are used to determine if a permission is granted. They are different from management providers: **value providers** are used when *checking* permissions, while **management providers** are used when *setting* permissions. 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..5e8c8a0454 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,17 +70,33 @@ 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) + public virtual async Task GetProviderKeyLookupServiceAsync(string serviceName) { var service = _lazyProviderKeyLookupServices.Value.FirstOrDefault(s => s.Name == serviceName); - return service == null - ? throw new AbpException("Unknown resource permission provider key lookup service: " + serviceName) - : Task.FromResult(service); + if (service == null) + { + throw new AbpException("Unknown resource permission provider key lookup service: " + serviceName); + } + + if (!await service.IsAvailableAsync()) + { + throw new AbpException("The resource permission provider key lookup service '" + serviceName + "' is not available in the current context."); + } + + return service; } public virtual async Task> GetAvailablePermissionsAsync(string resourceName) @@ -159,13 +175,15 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD { var resourcePermissionDefinitions = await GetAvailablePermissionsAsync(resourceName); var resourcePermissionGrants = await ResourcePermissionGrantRepository.GetPermissionsAsync(resourceName, resourceKey); + var unavailableProviderNames = await GetUnavailableManagementProviderNamesAsync(); var result = new List(); foreach (var resourcePermissionDefinition in resourcePermissionDefinitions) { var permissionWithGrantedProviders = new PermissionWithGrantedProviders(resourcePermissionDefinition.Name, false); var grantedPermissions = resourcePermissionGrants - .Where(x => x.Name == resourcePermissionDefinition.Name && x.ResourceName == resourceName && x.ResourceKey == resourceKey) + .Where(x => x.Name == resourcePermissionDefinition.Name && x.ResourceName == resourceName && x.ResourceKey == resourceKey + && !unavailableProviderNames.Contains(x.ProviderName)) .ToList(); if (grantedPermissions.Any()) @@ -194,7 +212,10 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD { var resourcePermissions = await GetAvailablePermissionsAsync(resourceName); var resourcePermissionGrants = await ResourcePermissionGrantRepository.GetPermissionsAsync(resourceName, resourceKey); - resourcePermissionGrants = resourcePermissionGrants.Where(x => resourcePermissions.Any(rp => rp.Name == x.Name)).ToList(); + var unavailableProviderNames = await GetUnavailableManagementProviderNamesAsync(); + resourcePermissionGrants = resourcePermissionGrants + .Where(x => resourcePermissions.Any(rp => rp.Name == x.Name) && !unavailableProviderNames.Contains(x.ProviderName)) + .ToList(); var resourcePermissionGrantsGroup = resourcePermissionGrants.GroupBy(x => new { x.ProviderName, x.ProviderKey }); var result = new List(); foreach (var resourcePermissionGrant in resourcePermissionGrantsGroup) @@ -282,6 +303,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); } @@ -327,6 +354,12 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD public virtual async Task DeleteAsync(string resourceName, string resourceKey, string providerName, string providerKey) { + var provider = ManagementProviders.FirstOrDefault(m => m.Name == providerName); + if (provider != null && !await provider.IsAvailableAsync()) + { + throw new AbpException($"The resource permission management provider '{providerName}' is not available in the current context."); + } + var permissionGrants = await ResourcePermissionGrantRepository.GetListAsync(resourceName, resourceKey, providerName, providerKey); foreach (var permissionGrant in permissionGrants) { @@ -336,6 +369,12 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD public virtual async Task DeleteAsync(string name, string resourceName, string resourceKey, string providerName, string providerKey) { + var provider = ManagementProviders.FirstOrDefault(m => m.Name == providerName); + if (provider != null && !await provider.IsAvailableAsync()) + { + throw new AbpException($"The resource permission management provider '{providerName}' is not available in the current context."); + } + var permissionGrant = await ResourcePermissionGrantRepository.FindAsync(name, resourceName, resourceKey, providerName, providerKey); if (permissionGrant != null) { @@ -378,6 +417,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); @@ -402,4 +446,17 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD return multiplePermissionWithGrantedProviders; } + + protected virtual async Task> GetUnavailableManagementProviderNamesAsync() + { + var names = new HashSet(); + foreach (var provider in ManagementProviders) + { + if (!await provider.IsAvailableAsync()) + { + names.Add(provider.Name); + } + } + return names; + } } 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..dc5cb4f4bd 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 @@ -42,6 +42,12 @@ public class ResourcePermissionManager_Tests : PermissionTestBase await _resourcePermissionManager.GetProviderKeyLookupServiceAsync("UndefinedProvider"); }); exception.Message.ShouldBe("Unknown resource permission provider key lookup service: UndefinedProvider"); + + var unavailableException = await Assert.ThrowsAsync(async () => + { + await _resourcePermissionManager.GetProviderKeyLookupServiceAsync("TestUnavailable"); + }); + unavailableException.Message.ShouldBe("The resource permission provider key lookup service 'TestUnavailable' is not available in the current context."); } [Fact] @@ -334,4 +340,135 @@ 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."); + } + + [Fact] + public async Task GetAllAsync_Should_Not_Include_Grants_From_Unavailable_Provider() + { + // Grant via the available "Test" provider and the unavailable "TestUnavailable" provider + await _resourcePermissionGrantRepository.InsertAsync(new ResourcePermissionGrant( + Guid.NewGuid(), + "MyResourcePermission1", + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1, + "Test", + "someKey") + ); + await _resourcePermissionGrantRepository.InsertAsync(new ResourcePermissionGrant( + Guid.NewGuid(), + "MyResourcePermission1", + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1, + "TestUnavailable", + "someKey") + ); + + var result = await _resourcePermissionManager.GetAllAsync( + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1); + + var item = result.FirstOrDefault(x => x.Name == "MyResourcePermission1"); + item.ShouldNotBeNull(); + item.IsGranted.ShouldBeTrue(); + item.Providers.ShouldContain(p => p.Name == "Test"); + item.Providers.ShouldNotContain(p => p.Name == "TestUnavailable"); + } + + [Fact] + public async Task GetAllGroupAsync_Should_Not_Include_Grants_From_Unavailable_Provider() + { + await _resourcePermissionGrantRepository.InsertAsync(new ResourcePermissionGrant( + Guid.NewGuid(), + "MyResourcePermission2", + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1, + "TestUnavailable", + "someKey") + ); + + var group = await _resourcePermissionManager.GetAllGroupAsync( + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1); + + group.ShouldNotContain(g => g.ProviderName == "TestUnavailable"); + } + + [Fact] + public async Task DeleteAsync_Should_Throw_When_Provider_Is_Unavailable() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _resourcePermissionManager.DeleteAsync( + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1, + "TestUnavailable", + "someKey"); + }); + exception.Message.ShouldBe("The resource permission management provider 'TestUnavailable' is not available in the current context."); + } + + [Fact] + public async Task DeleteAsyncByName_Should_Throw_When_Provider_Is_Unavailable() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _resourcePermissionManager.DeleteAsync( + "MyResourcePermission1", + TestEntityResource.ResourceName, + TestEntityResource.ResourceKey1, + "TestUnavailable", + "someKey"); + }); + 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(); + } +}