Browse Source

Provide a way to clear the `application configuration` cache for all users.

https://abp.io/support/questions/10259
pull/24486/head
maliming 1 month ago
parent
commit
a565abc59a
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 3
      framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiCurrentApplicationConfigurationCacheResetService.cs
  2. 9
      framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Configuration/BlazorServerCurrentApplicationConfigurationCacheResetService.cs
  3. 5
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/ICurrentApplicationConfigurationCacheResetService.cs
  4. 3
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/NullCurrentApplicationConfigurationCacheResetService.cs
  5. 3
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Configuration/BlazorWebAssemblyCurrentApplicationConfigurationCacheResetService.cs
  6. 25
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs
  7. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationVersionCacheItem.cs
  8. 7
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs
  9. 14
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs
  10. 27
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCurrentApplicationConfigurationCacheResetEventHandler.cs
  11. 14
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentApplicationConfigurationCacheResetEventData.cs
  12. 9
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs
  13. 14
      modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs

3
framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiCurrentApplicationConfigurationCacheResetService.cs

@ -1,3 +1,4 @@
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Components.Web.Configuration; using Volo.Abp.AspNetCore.Components.Web.Configuration;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -16,7 +17,7 @@ public class MauiCurrentApplicationConfigurationCacheResetService :
_mauiBlazorCachedApplicationConfigurationClient = mauiBlazorCachedApplicationConfigurationClient; _mauiBlazorCachedApplicationConfigurationClient = mauiBlazorCachedApplicationConfigurationClient;
} }
public async Task ResetAsync() public async Task ResetAsync(Guid? userId = null)
{ {
await _mauiBlazorCachedApplicationConfigurationClient.InitializeAsync(); await _mauiBlazorCachedApplicationConfigurationClient.InitializeAsync();
} }

9
framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Configuration/BlazorServerCurrentApplicationConfigurationCacheResetService.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks; using System;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Components.Web.Configuration; using Volo.Abp.AspNetCore.Components.Web.Configuration;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -19,10 +20,8 @@ public class BlazorServerCurrentApplicationConfigurationCacheResetService :
_localEventBus = localEventBus; _localEventBus = localEventBus;
} }
public async Task ResetAsync() public async Task ResetAsync(Guid? userId = null)
{ {
await _localEventBus.PublishAsync( await _localEventBus.PublishAsync(new CurrentApplicationConfigurationCacheResetEventData(userId));
new CurrentApplicationConfigurationCacheResetEventData()
);
} }
} }

5
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/ICurrentApplicationConfigurationCacheResetService.cs

@ -1,8 +1,9 @@
using System.Threading.Tasks; using System;
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web.Configuration; namespace Volo.Abp.AspNetCore.Components.Web.Configuration;
public interface ICurrentApplicationConfigurationCacheResetService public interface ICurrentApplicationConfigurationCacheResetService
{ {
Task ResetAsync(); Task ResetAsync(Guid? userId = null);
} }

3
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/NullCurrentApplicationConfigurationCacheResetService.cs

@ -1,3 +1,4 @@
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -5,7 +6,7 @@ namespace Volo.Abp.AspNetCore.Components.Web.Configuration;
public class NullCurrentApplicationConfigurationCacheResetService : ICurrentApplicationConfigurationCacheResetService, ISingletonDependency public class NullCurrentApplicationConfigurationCacheResetService : ICurrentApplicationConfigurationCacheResetService, ISingletonDependency
{ {
public Task ResetAsync() public Task ResetAsync(Guid? userId = null)
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }

3
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Configuration/BlazorWebAssemblyCurrentApplicationConfigurationCacheResetService.cs

@ -1,3 +1,4 @@
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Components.Web.Configuration; using Volo.Abp.AspNetCore.Components.Web.Configuration;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -16,7 +17,7 @@ public class BlazorWebAssemblyCurrentApplicationConfigurationCacheResetService :
_webAssemblyCachedApplicationConfigurationClient = webAssemblyCachedApplicationConfigurationClient; _webAssemblyCachedApplicationConfigurationClient = webAssemblyCachedApplicationConfigurationClient;
} }
public async Task ResetAsync() public async Task ResetAsync(Guid? userId = null)
{ {
await _webAssemblyCachedApplicationConfigurationClient.InitializeAsync(); await _webAssemblyCachedApplicationConfigurationClient.InitializeAsync();
} }

25
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs

@ -1,13 +1,26 @@
using System.Globalization; using System;
using Volo.Abp.Users; using System.Globalization;
using System.Threading.Tasks;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.Client; namespace Volo.Abp.AspNetCore.Mvc.Client;
public static class MvcCachedApplicationConfigurationClientHelper public class MvcCachedApplicationConfigurationClientHelper : ITransientDependency
{ {
public static string CreateCacheKey(ICurrentUser currentUser) protected IDistributedCache<MvcCachedApplicationVersionCacheItem> ApplicationVersionCache { get; }
public MvcCachedApplicationConfigurationClientHelper(IDistributedCache<MvcCachedApplicationVersionCacheItem> applicationVersionCache)
{
ApplicationVersionCache = applicationVersionCache;
}
public virtual async Task<string> CreateCacheKeyAsync(Guid? userId)
{ {
var userKey = currentUser.Id?.ToString("N") ?? "Anonymous"; var appVersion = await ApplicationVersionCache.GetOrAddAsync(MvcCachedApplicationVersionCacheItem.CacheKey,
return $"ApplicationConfiguration_{userKey}_{CultureInfo.CurrentUICulture.Name}"; () => Task.FromResult(new MvcCachedApplicationVersionCacheItem(Guid.NewGuid().ToString()))) ??
new MvcCachedApplicationVersionCacheItem(Guid.NewGuid().ToString());
var userKey = userId?.ToString("N") ?? "Anonymous";
return $"ApplicationConfiguration_{appVersion}_{userKey}_{CultureInfo.CurrentUICulture.Name}";
} }
} }

13
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationVersionCacheItem.cs

@ -0,0 +1,13 @@
namespace Volo.Abp.AspNetCore.Mvc.Client;
public class MvcCachedApplicationVersionCacheItem
{
public const string CacheKey = "Mvc_Application_Version";
public string Version { get; set; }
public MvcCachedApplicationVersionCacheItem(string version)
{
Version = version;
}
}

7
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs

@ -20,6 +20,7 @@ public class RemoteDynamicClaimsPrincipalContributorCache : RemoteDynamicClaimsP
protected IHttpClientFactory HttpClientFactory { get; } protected IHttpClientFactory HttpClientFactory { get; }
protected IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } protected IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; }
protected IDistributedCache<ApplicationConfigurationDto> ApplicationConfigurationDtoCache { get; } protected IDistributedCache<ApplicationConfigurationDto> ApplicationConfigurationDtoCache { get; }
protected MvcCachedApplicationConfigurationClientHelper CacheHelper { get; }
protected ICurrentUser CurrentUser { get; } protected ICurrentUser CurrentUser { get; }
public RemoteDynamicClaimsPrincipalContributorCache( public RemoteDynamicClaimsPrincipalContributorCache(
@ -28,7 +29,8 @@ public class RemoteDynamicClaimsPrincipalContributorCache : RemoteDynamicClaimsP
IOptions<AbpClaimsPrincipalFactoryOptions> abpClaimsPrincipalFactoryOptions, IOptions<AbpClaimsPrincipalFactoryOptions> abpClaimsPrincipalFactoryOptions,
IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, IRemoteServiceHttpClientAuthenticator httpClientAuthenticator,
IDistributedCache<ApplicationConfigurationDto> applicationConfigurationDtoCache, IDistributedCache<ApplicationConfigurationDto> applicationConfigurationDtoCache,
ICurrentUser currentUser) ICurrentUser currentUser,
MvcCachedApplicationConfigurationClientHelper cacheHelper)
: base(abpClaimsPrincipalFactoryOptions) : base(abpClaimsPrincipalFactoryOptions)
{ {
Cache = cache; Cache = cache;
@ -36,6 +38,7 @@ public class RemoteDynamicClaimsPrincipalContributorCache : RemoteDynamicClaimsP
HttpClientAuthenticator = httpClientAuthenticator; HttpClientAuthenticator = httpClientAuthenticator;
ApplicationConfigurationDtoCache = applicationConfigurationDtoCache; ApplicationConfigurationDtoCache = applicationConfigurationDtoCache;
CurrentUser = currentUser; CurrentUser = currentUser;
CacheHelper = cacheHelper;
} }
protected async override Task<AbpDynamicClaimCacheItem?> GetCacheAsync(Guid userId, Guid? tenantId = null) protected async override Task<AbpDynamicClaimCacheItem?> GetCacheAsync(Guid userId, Guid? tenantId = null)
@ -56,7 +59,7 @@ public class RemoteDynamicClaimsPrincipalContributorCache : RemoteDynamicClaimsP
catch (Exception e) catch (Exception e)
{ {
Logger.LogWarning(e, $"Failed to refresh remote claims for user: {userId}"); Logger.LogWarning(e, $"Failed to refresh remote claims for user: {userId}");
await ApplicationConfigurationDtoCache.RemoveAsync(MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser)); await ApplicationConfigurationDtoCache.RemoveAsync(await CacheHelper.CreateCacheKeyAsync(CurrentUser.Id));
throw; throw;
} }
} }

14
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs

@ -1,3 +1,4 @@
using System;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
@ -17,10 +18,12 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu
protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; } protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; }
protected AbpApplicationLocalizationClientProxy ApplicationLocalizationClientProxy { get; } protected AbpApplicationLocalizationClientProxy ApplicationLocalizationClientProxy { get; }
protected ICurrentUser CurrentUser { get; } protected ICurrentUser CurrentUser { get; }
protected MvcCachedApplicationConfigurationClientHelper CacheHelper { get; }
protected IDistributedCache<ApplicationConfigurationDto> Cache { get; } protected IDistributedCache<ApplicationConfigurationDto> Cache { get; }
protected AbpAspNetCoreMvcClientCacheOptions Options { get; } protected AbpAspNetCoreMvcClientCacheOptions Options { get; }
public MvcCachedApplicationConfigurationClient( public MvcCachedApplicationConfigurationClient(
MvcCachedApplicationConfigurationClientHelper cacheHelper,
IDistributedCache<ApplicationConfigurationDto> cache, IDistributedCache<ApplicationConfigurationDto> cache,
AbpApplicationConfigurationClientProxy applicationConfigurationAppService, AbpApplicationConfigurationClientProxy applicationConfigurationAppService,
ICurrentUser currentUser, ICurrentUser currentUser,
@ -33,12 +36,13 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu
HttpContextAccessor = httpContextAccessor; HttpContextAccessor = httpContextAccessor;
ApplicationLocalizationClientProxy = applicationLocalizationClientProxy; ApplicationLocalizationClientProxy = applicationLocalizationClientProxy;
Options = options.Value; Options = options.Value;
CacheHelper = cacheHelper;
Cache = cache; Cache = cache;
} }
public async Task<ApplicationConfigurationDto> GetAsync() public virtual async Task<ApplicationConfigurationDto> GetAsync()
{ {
var cacheKey = CreateCacheKey(); var cacheKey = await CreateCacheKeyAsync();
var httpContext = HttpContextAccessor?.HttpContext; var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration) if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration)
@ -86,7 +90,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu
public ApplicationConfigurationDto Get() public ApplicationConfigurationDto Get()
{ {
var cacheKey = CreateCacheKey(); var cacheKey = AsyncHelper.RunSync(CreateCacheKeyAsync);
var httpContext = HttpContextAccessor?.HttpContext; var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration) if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration)
@ -97,8 +101,8 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu
return AsyncHelper.RunSync(GetAsync); return AsyncHelper.RunSync(GetAsync);
} }
protected virtual string CreateCacheKey() protected virtual async Task<string> CreateCacheKeyAsync()
{ {
return MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser); return await CacheHelper.CreateCacheKeyAsync(CurrentUser.Id);
} }
} }

27
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCurrentApplicationConfigurationCacheResetEventHandler.cs

@ -3,7 +3,6 @@ using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus; using Volo.Abp.EventBus;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.Client; namespace Volo.Abp.AspNetCore.Mvc.Client;
@ -11,23 +10,29 @@ public class MvcCurrentApplicationConfigurationCacheResetEventHandler :
ILocalEventHandler<CurrentApplicationConfigurationCacheResetEventData>, ILocalEventHandler<CurrentApplicationConfigurationCacheResetEventData>,
ITransientDependency ITransientDependency
{ {
protected ICurrentUser CurrentUser { get; }
protected IDistributedCache<ApplicationConfigurationDto> Cache { get; } protected IDistributedCache<ApplicationConfigurationDto> Cache { get; }
protected IDistributedCache<MvcCachedApplicationVersionCacheItem> ApplicationVersionCache { get; }
protected MvcCachedApplicationConfigurationClientHelper CacheHelper { get; }
public MvcCurrentApplicationConfigurationCacheResetEventHandler(ICurrentUser currentUser, public MvcCurrentApplicationConfigurationCacheResetEventHandler(
IDistributedCache<ApplicationConfigurationDto> cache) IDistributedCache<ApplicationConfigurationDto> cache,
IDistributedCache<MvcCachedApplicationVersionCacheItem> applicationVersionCache,
MvcCachedApplicationConfigurationClientHelper cacheHelper)
{ {
CurrentUser = currentUser;
Cache = cache; Cache = cache;
ApplicationVersionCache = applicationVersionCache;
CacheHelper = cacheHelper;
} }
public virtual async Task HandleEventAsync(CurrentApplicationConfigurationCacheResetEventData eventData) public virtual async Task HandleEventAsync(CurrentApplicationConfigurationCacheResetEventData eventData)
{ {
await Cache.RemoveAsync(CreateCacheKey()); if (eventData.UserId.HasValue)
} {
await Cache.RemoveAsync(await CacheHelper.CreateCacheKeyAsync(eventData.UserId));
protected virtual string CreateCacheKey() }
{ else
return MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser); {
await ApplicationVersionCache.RemoveAsync(MvcCachedApplicationVersionCacheItem.CacheKey);
}
} }
} }

14
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentApplicationConfigurationCacheResetEventData.cs

@ -1,9 +1,21 @@
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using System;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
/// <summary> /// <summary>
/// This event is used to invalidate current user's cached configuration. /// This event is used to invalidate current user's cached configuration.
/// </summary> /// </summary>
public class CurrentApplicationConfigurationCacheResetEventData public class CurrentApplicationConfigurationCacheResetEventData
{ {
public Guid? UserId { get; set; }
public CurrentApplicationConfigurationCacheResetEventData()
{
}
public CurrentApplicationConfigurationCacheResetEventData(Guid? userId)
{
UserId = userId;
}
} }

9
modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs

@ -6,6 +6,7 @@ using Blazorise;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Components.Web.Configuration; using Volo.Abp.AspNetCore.Components.Web.Configuration;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.PermissionManagement.Localization; using Volo.Abp.PermissionManagement.Localization;
@ -153,7 +154,13 @@ public partial class PermissionManagementModal
await PermissionAppService.UpdateAsync(_providerName, _providerKey, updateDto); await PermissionAppService.UpdateAsync(_providerName, _providerKey, updateDto);
await CurrentApplicationConfigurationCacheResetService.ResetAsync(); Guid? userId = null;
if (_providerName == UserPermissionValueProvider.ProviderName && Guid.TryParse(_providerKey, out var parsedUserId))
{
userId = parsedUserId;
}
await CurrentApplicationConfigurationCacheResetService.ResetAsync(userId);
await InvokeAsync(_modal.Hide); await InvokeAsync(_modal.Hide);
await Notify.Success(L["SavedSuccessfully"]); await Notify.Success(L["SavedSuccessfully"]);

14
modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
@ -6,6 +7,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.EventBus.Local; using Volo.Abp.EventBus.Local;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.PermissionManagement.Web.Utils; using Volo.Abp.PermissionManagement.Web.Utils;
@ -105,9 +107,13 @@ public class PermissionManagementModal : AbpPageModel
} }
); );
await LocalEventBus.PublishAsync( Guid? userId = null;
new CurrentApplicationConfigurationCacheResetEventData() if (ProviderName == UserPermissionValueProvider.ProviderName && Guid.TryParse(ProviderName, out var parsedUserId))
); {
userId = parsedUserId;
}
await LocalEventBus.PublishAsync(new CurrentApplicationConfigurationCacheResetEventData(userId));
return NoContent(); return NoContent();
} }
@ -130,7 +136,7 @@ public class PermissionManagementModal : AbpPageModel
public bool IsDisabled(string currentProviderName) public bool IsDisabled(string currentProviderName)
{ {
var grantedProviders = Permissions.SelectMany(x => x.GrantedProviders); var grantedProviders = Permissions.SelectMany(x => x.GrantedProviders);
return Permissions.All(x => x.IsGranted) && grantedProviders.All(p => p.ProviderName != currentProviderName); return Permissions.All(x => x.IsGranted) && grantedProviders.All(p => p.ProviderName != currentProviderName);
} }
} }

Loading…
Cancel
Save