diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs index 18f5272e7b..66f9aea05a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs @@ -1,4 +1,5 @@ -using System.Security.Claims; +using System.Collections.Generic; +using System.Security.Claims; using System.Threading.Tasks; using Volo.Abp.Authorization.Permissions; using Volo.Abp.DependencyInjection; @@ -26,5 +27,25 @@ namespace Volo.Abp.AspNetCore.Mvc.Client /* This provider always works for the current principal. */ return await IsGrantedAsync(name); } + + public async Task IsGrantedAsync(string[] names) + { + var result = new MultiplePermissionGrantResult(); + var configuration = await ConfigurationClient.GetAsync(); + foreach (var name in names) + { + result.Result.Add(name, configuration.Auth.GrantedPolicies.ContainsKey(name) ? + PermissionGrantResult.Granted : + PermissionGrantResult.Undefined); + } + + return result; + } + + public async Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string[] names) + { + /* This provider always works for the current principal. */ + return await IsGrantedAsync(names); + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs index 89bf3e7cfc..e02132a84a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs @@ -5,12 +5,14 @@ using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Volo.Abp.Application.Services; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; using Volo.Abp.AspNetCore.Mvc.MultiTenancy; using Volo.Abp.Authorization; +using Volo.Abp.Authorization.Permissions; using Volo.Abp.Features; using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; @@ -26,6 +28,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations private readonly AbpMultiTenancyOptions _multiTenancyOptions; private readonly IServiceProvider _serviceProvider; private readonly IAbpAuthorizationPolicyProvider _abpAuthorizationPolicyProvider; + private readonly IPermissionDefinitionManager _permissionDefinitionManager; + private readonly DefaultAuthorizationPolicyProvider _defaultAuthorizationPolicyProvider; + private readonly IPermissionChecker _permissionChecker; private readonly IAuthorizationService _authorizationService; private readonly ICurrentUser _currentUser; private readonly ISettingProvider _settingProvider; @@ -41,6 +46,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations IOptions multiTenancyOptions, IServiceProvider serviceProvider, IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider, + IPermissionDefinitionManager permissionDefinitionManager, + DefaultAuthorizationPolicyProvider defaultAuthorizationPolicyProvider, + IPermissionChecker permissionChecker, IAuthorizationService authorizationService, ICurrentUser currentUser, ISettingProvider settingProvider, @@ -53,6 +61,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations { _serviceProvider = serviceProvider; _abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider; + _permissionDefinitionManager = permissionDefinitionManager; + _defaultAuthorizationPolicyProvider = defaultAuthorizationPolicyProvider; + _permissionChecker = permissionChecker; _authorizationService = authorizationService; _currentUser = currentUser; _settingProvider = settingProvider; @@ -132,8 +143,22 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations var authConfig = new ApplicationAuthConfigurationDto(); var policyNames = await _abpAuthorizationPolicyProvider.GetPoliciesNamesAsync(); + var abpPolicyNames = new List(); + var otherPolicyNames = new List(); foreach (var policyName in policyNames) + { + if(await _defaultAuthorizationPolicyProvider.GetPolicyAsync(policyName) == null && _permissionDefinitionManager.GetOrNull(policyName) != null) + { + abpPolicyNames.Add(policyName); + } + else + { + otherPolicyNames.Add(policyName); + } + } + + foreach (var policyName in otherPolicyNames) { authConfig.Policies[policyName] = true; @@ -143,6 +168,16 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations } } + var result = await _permissionChecker.IsGrantedAsync(abpPolicyNames.ToArray()); + foreach (var (key, value) in result.Result) + { + authConfig.Policies[key] = true; + if (value == PermissionGrantResult.Granted) + { + authConfig.GrantedPolicies[key] = true; + } + } + return authConfig; } 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 86b2b18d04..b16e08a214 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Localization; using Volo.Abp.Modularity; @@ -29,6 +30,8 @@ namespace Volo.Abp.Authorization context.Services.AddSingleton(); + context.Services.TryAddTransient(); + Configure(options => { options.ValueProviders.Add(); diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/AlwaysAllowPermissionChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/AlwaysAllowPermissionChecker.cs index e3f4425289..9efcfeb293 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/AlwaysAllowPermissionChecker.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/AlwaysAllowPermissionChecker.cs @@ -1,4 +1,6 @@ -using System.Security.Claims; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; using Volo.Abp.Threading; @@ -6,7 +8,7 @@ namespace Volo.Abp.Authorization.Permissions { /// /// Always allows for any permission. - /// + /// /// Use IServiceCollection.AddAlwaysAllowAuthorization() to replace /// IPermissionChecker with this class. This is useful for tests. /// @@ -21,5 +23,20 @@ namespace Volo.Abp.Authorization.Permissions { return TaskCache.TrueResult; } + + public Task IsGrantedAsync(string[] names) + { + return IsGrantedAsync(null, names); + } + + public Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string[] names) + { + var result = new MultiplePermissionGrantResult(); + foreach (var name in names) + { + result.Result.Add(name, PermissionGrantResult.Granted); + } + return Task.FromResult(result); + } } } diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/ClientPermissionValueProvider.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/ClientPermissionValueProvider.cs index c1d9b3a6dc..5e9f34767b 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/ClientPermissionValueProvider.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/ClientPermissionValueProvider.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using Volo.Abp.Security.Claims; namespace Volo.Abp.Authorization.Permissions @@ -28,5 +30,23 @@ namespace Volo.Abp.Authorization.Permissions ? PermissionGrantResult.Granted : PermissionGrantResult.Undefined; } + + public async override Task CheckAsync(PermissionValuesCheckContext context) + { + var result = new MultiplePermissionGrantResult(); + var permissionNames = context.Permissions.Select(x => x.Name).ToList(); + foreach (var name in permissionNames) + { + result.Result.Add(name, PermissionGrantResult.Undefined); + } + + var clientId = context.Principal?.FindFirst(AbpClaimTypes.ClientId)?.Value; + if (clientId == null) + { + return result; + } + + return await PermissionStore.IsGrantedAsync(permissionNames.ToArray(), Name, clientId); + } } } diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionChecker.cs index b394a29f52..91987b408d 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionChecker.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionChecker.cs @@ -1,4 +1,5 @@ -using System.Security.Claims; +using System.Collections.Generic; +using System.Security.Claims; using System.Threading.Tasks; using JetBrains.Annotations; @@ -9,5 +10,9 @@ namespace Volo.Abp.Authorization.Permissions Task IsGrantedAsync([NotNull]string name); Task IsGrantedAsync([CanBeNull] ClaimsPrincipal claimsPrincipal, [NotNull]string name); + + Task IsGrantedAsync([NotNull]string[] names); + + Task IsGrantedAsync([CanBeNull] ClaimsPrincipal claimsPrincipal, [NotNull]string[] names); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionStore.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionStore.cs index b2d077d3c7..08ca09fc72 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionStore.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionStore.cs @@ -10,5 +10,11 @@ namespace Volo.Abp.Authorization.Permissions [CanBeNull] string providerName, [CanBeNull] string providerKey ); + + Task IsGrantedAsync( + [NotNull] string[] names, + [CanBeNull] string providerName, + [CanBeNull] string providerKey + ); } } diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs index a9b5e78337..9d69b6d55d 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Volo.Abp.Authorization.Permissions { @@ -8,5 +9,7 @@ namespace Volo.Abp.Authorization.Permissions //TODO: Rename to GetResult? (CheckAsync throws exception by naming convention) Task CheckAsync(PermissionValueCheckContext context); + + Task CheckAsync(PermissionValuesCheckContext context); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/MultiplePermissionGrantResult.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/MultiplePermissionGrantResult.cs new file mode 100644 index 0000000000..dd0aff0633 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/MultiplePermissionGrantResult.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Authorization.Permissions +{ + public class MultiplePermissionGrantResult + { + public bool AllGranted + { + get + { + return Result.Values.All(x => x == PermissionGrantResult.Granted); + } + } + + public bool AllProhibited + { + get + { + return Result.Values.All(x => x == PermissionGrantResult.Prohibited); + } + } + + public Dictionary Result { get; } + + public MultiplePermissionGrantResult() + { + Result = new Dictionary(); + } + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullPermissionStore.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullPermissionStore.cs index 57c76ac6c9..df2311d6b6 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullPermissionStore.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullPermissionStore.cs @@ -19,5 +19,15 @@ namespace Volo.Abp.Authorization.Permissions { return TaskCache.FalseResult; } + + public Task IsGrantedAsync(string[] names, string providerName, string providerKey) + { + var result = new MultiplePermissionGrantResult(); + foreach (var name in names) + { + result.Result.Add(name, PermissionGrantResult.Prohibited); + } + return Task.FromResult(result); + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs index 931c9d1d23..49f5ba24e5 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Security.Claims; using System.Security.Principal; using System.Threading.Tasks; @@ -17,7 +18,7 @@ namespace Volo.Abp.Authorization.Permissions public PermissionChecker( ICurrentPrincipalAccessor principalAccessor, - IPermissionDefinitionManager permissionDefinitionManager, + IPermissionDefinitionManager permissionDefinitionManager, ICurrentTenant currentTenant, IPermissionValueProviderManager permissionValueProviderManager) { @@ -33,7 +34,7 @@ namespace Volo.Abp.Authorization.Permissions } public virtual async Task IsGrantedAsync( - ClaimsPrincipal claimsPrincipal, + ClaimsPrincipal claimsPrincipal, string name) { Check.NotNull(name, nameof(name)); @@ -77,5 +78,58 @@ namespace Volo.Abp.Authorization.Permissions return isGranted; } + + public async Task IsGrantedAsync(string[] names) + { + return await IsGrantedAsync(PrincipalAccessor.Principal, names); + } + + public async Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string[] names) + { + Check.NotNull(names, nameof(names)); + + var multiTenancySide = claimsPrincipal?.GetMultiTenancySide() + ?? CurrentTenant.GetMultiTenancySide(); + + var result = new MultiplePermissionGrantResult(); + + var definitions = new List(); + foreach (var name in names) + { + var permission = PermissionDefinitionManager.Get(name); + if (!permission.IsEnabled || !permission.MultiTenancySide.HasFlag(multiTenancySide)) + { + result.Result.Add(name, PermissionGrantResult.Undefined); + continue; + } + + result.Result.Add(name, PermissionGrantResult.Undefined); + definitions.Add(permission); + } + + foreach (var provider in PermissionValueProviderManager.ValueProviders) + { + var context = new PermissionValuesCheckContext(definitions.Where(x => !x.Providers.Any() || x.Providers.Contains(provider.Name)).ToList(), + claimsPrincipal); + + foreach (var grantResult in (await provider.CheckAsync(context)).Result) + { + if (result.Result.ContainsKey(grantResult.Key) && + result.Result[grantResult.Key] == PermissionGrantResult.Undefined && + grantResult.Value != PermissionGrantResult.Undefined) + { + result.Result[grantResult.Key] = grantResult.Value; + definitions.Remove(definitions.First(x => x.Name == grantResult.Key)); + } + + if (result.AllGranted || result.AllProhibited) + { + break; + } + } + } + + return result; + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs index d15311b77c..47ed4e7722 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Authorization.Permissions @@ -15,5 +16,7 @@ namespace Volo.Abp.Authorization.Permissions } public abstract Task CheckAsync(PermissionValueCheckContext context); + + public abstract Task CheckAsync(PermissionValuesCheckContext context); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValuesCheckContext.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValuesCheckContext.cs new file mode 100644 index 0000000000..e9014eff94 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValuesCheckContext.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Security.Claims; +using JetBrains.Annotations; + +namespace Volo.Abp.Authorization.Permissions +{ + public class PermissionValuesCheckContext + { + [NotNull] + public List Permissions { get; } + + [CanBeNull] + public ClaimsPrincipal Principal { get; } + + public PermissionValuesCheckContext( + [NotNull] List permissions, + [CanBeNull] ClaimsPrincipal principal) + { + Check.NotNull(permissions, nameof(permissions)); + + Permissions = permissions; + Principal = principal; + } + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs index a458cd8fdb..5ae21a3ecc 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Volo.Abp.Security.Claims; @@ -35,5 +36,42 @@ namespace Volo.Abp.Authorization.Permissions return PermissionGrantResult.Undefined; } + + public async override Task CheckAsync(PermissionValuesCheckContext context) + { + var result = new MultiplePermissionGrantResult(); + var permissionNames = context.Permissions.Select(x => x.Name).ToList(); + foreach (var name in permissionNames) + { + result.Result.Add(name, PermissionGrantResult.Undefined); + } + + var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray(); + if (roles == null || !roles.Any()) + { + return result; + } + + foreach (var role in roles) + { + foreach (var grantResult in (await PermissionStore.IsGrantedAsync(permissionNames.ToArray(), Name, role)).Result) + { + if (result.Result.ContainsKey(grantResult.Key) && + result.Result[grantResult.Key] == PermissionGrantResult.Undefined && + grantResult.Value != PermissionGrantResult.Undefined) + { + result.Result[grantResult.Key] = grantResult.Value; + permissionNames.Remove(grantResult.Key); + } + } + + if (result.AllGranted) + { + break; + } + } + + return result; + } } } diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/UserPermissionValueProvider.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/UserPermissionValueProvider.cs index 204b928e61..ae40285cee 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/UserPermissionValueProvider.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/UserPermissionValueProvider.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using Volo.Abp.Security.Claims; namespace Volo.Abp.Authorization.Permissions @@ -28,5 +30,23 @@ namespace Volo.Abp.Authorization.Permissions ? PermissionGrantResult.Granted : PermissionGrantResult.Undefined; } + + public async override Task CheckAsync(PermissionValuesCheckContext context) + { + var result = new MultiplePermissionGrantResult(); + var permissionNames = context.Permissions.Select(x => x.Name).ToList(); + foreach (var name in permissionNames) + { + result.Result.Add(name, PermissionGrantResult.Undefined); + } + + var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value; + if (userId == null) + { + return result; + } + + return await PermissionStore.IsGrantedAsync(permissionNames.ToArray(), Name, userId); + } } } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/FakePermissionStore.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/FakePermissionStore.cs index 175e281716..6509d6dce2 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/FakePermissionStore.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/FakePermissionStore.cs @@ -14,5 +14,20 @@ namespace Volo.Abp.AspNetCore.Mvc.Authorization return Task.FromResult(result); } + + public Task IsGrantedAsync(string[] names, string providerName, string providerKey) + { + var result = new MultiplePermissionGrantResult(); + foreach (var name in names) + { + result.Result.Add(name, name == "TestPermission1" && + providerName == UserPermissionValueProvider.ProviderName && + providerKey == AuthTestController.FakeUserId.ToString() + ? PermissionGrantResult.Granted + : PermissionGrantResult.Undefined); + } + + return Task.FromResult(result); + } } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItem.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItem.cs index 49013954a2..47a7e1530c 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItem.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItem.cs @@ -1,4 +1,6 @@ using System; +using System.Linq; +using Volo.Abp.Text.Formatting; namespace Volo.Abp.PermissionManagement { @@ -21,5 +23,12 @@ namespace Volo.Abp.PermissionManagement { return "pn:" + providerName + ",pk:" + providerKey + ",n:" + name; } + + public static string ParseCacheKeyOrNull(string key) + { + var format = "pn:{0},pk:{1},n:{2}"; + var result = FormattedStringValueExtracter.Extract(key, format, true); + return result.IsMatch ? result.Matches.Last().Value : null; + } } -} \ No newline at end of file +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionStore.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionStore.cs index bdfdc38881..b80c0b3fa1 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionStore.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionStore.cs @@ -35,6 +35,21 @@ namespace Volo.Abp.PermissionManagement return (await GetCacheItemAsync(name, providerName, providerKey)).IsGranted; } + public virtual async Task IsGrantedAsync(string[] names, string providerName, string providerKey) + { + var result = new MultiplePermissionGrantResult(); + + var cacheItems = await GetCacheItemsAsync(names, providerName, providerKey); + foreach (var item in cacheItems) + { + result.Result.Add(PermissionGrantCacheItem.ParseCacheKeyOrNull(item.Key), item.Value.IsGranted + ? PermissionGrantResult.Granted : + PermissionGrantResult.Undefined); + } + + return result; + } + protected virtual async Task GetCacheItemAsync( string name, string providerName, @@ -53,9 +68,9 @@ namespace Volo.Abp.PermissionManagement } Logger.LogDebug($"Not found in the cache: {cacheKey}"); - + cacheItem = new PermissionGrantCacheItem(false); - + await SetCacheItemsAsync(providerName, providerKey, name, cacheItem); return cacheItem; @@ -68,7 +83,7 @@ namespace Volo.Abp.PermissionManagement PermissionGrantCacheItem currentCacheItem) { var permissions = PermissionDefinitionManager.GetPermissions(); - + Logger.LogDebug($"Getting all granted permissions from the repository for this provider name,key: {providerName},{providerKey}"); var grantedPermissionsHashSet = new HashSet( @@ -87,7 +102,7 @@ namespace Volo.Abp.PermissionManagement CalculateCacheKey(permission.Name, providerName, providerKey), new PermissionGrantCacheItem(isGranted)) ); - + if (permission.Name == currentName) { currentCacheItem.IsGranted = isGranted; @@ -95,13 +110,64 @@ namespace Volo.Abp.PermissionManagement } await Cache.SetManyAsync(cacheItems); - + Logger.LogDebug($"Finished setting the cache items. Count: {permissions.Count}"); } + protected virtual async Task>> GetCacheItemsAsync( + string[] names, + string providerName, + string providerKey) + { + var cacheKeys = names.Select(x => CalculateCacheKey(x, providerName, providerKey)).ToList(); + var cacheItems = (await Cache.GetManyAsync(cacheKeys)).ToList(); + if (cacheItems.All(x => x.Value != null)) + { + return cacheItems; + } + + return cacheItems.Where(x => x.Value != null) + .Union(await SetCacheItemsAsync(providerName, providerKey, cacheItems.Where(x => x.Value == null))) + .ToList(); + } + + protected virtual async Task>> SetCacheItemsAsync( + string providerName, + string providerKey, + IEnumerable> notCacheItems) + { + var permissions = PermissionDefinitionManager.GetPermissions(); + + Logger.LogDebug($"Getting all granted permissions from the repository for this provider name,key: {providerName},{providerKey}"); + + var grantedPermissionsHashSet = new HashSet( + (await PermissionGrantRepository.GetListAsync(providerName, providerKey)).Select(p => p.Name) + ); + + Logger.LogDebug($"Setting the cache items. Count: {permissions.Count}"); + + var cacheItems = new List>(); + + foreach (var permission in permissions) + { + var isGranted = grantedPermissionsHashSet.Contains(permission.Name); + + cacheItems.Add(new KeyValuePair( + CalculateCacheKey(permission.Name, providerName, providerKey), + new PermissionGrantCacheItem(isGranted)) + ); + } + + await Cache.SetManyAsync(cacheItems); + + Logger.LogDebug($"Finished setting the cache items. Count: {permissions.Count}"); + + return cacheItems.Where(x => notCacheItems.Any(y => x.Key == y.Key)).ToList(); + } + protected virtual string CalculateCacheKey(string name, string providerName, string providerKey) { return PermissionGrantCacheItem.CalculateCacheKey(name, providerName, providerKey); } } -} \ No newline at end of file +}