mirror of https://github.com/abpframework/abp.git
Browse Source
Resolve #6969 https://identityserver4.readthedocs.io/en/latest/reference/options.html#cachingpull/7856/head
7 changed files with 459 additions and 22 deletions
@ -0,0 +1,74 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Entities.Events; |
|||
using Volo.Abp.EventBus; |
|||
using Volo.Abp.IdentityServer.Clients; |
|||
using Volo.Abp.IdentityServer.ApiResources; |
|||
using Volo.Abp.IdentityServer.ApiScopes; |
|||
using Volo.Abp.IdentityServer.IdentityResources; |
|||
|
|||
namespace Volo.Abp.IdentityServer |
|||
{ |
|||
public class IdentityServerCacheItemInvalidator : |
|||
ILocalEventHandler<EntityChangedEventData<Client>>, |
|||
ILocalEventHandler<EntityChangedEventData<ClientCorsOrigin>>, |
|||
ILocalEventHandler<EntityChangedEventData<IdentityResource>>, |
|||
ILocalEventHandler<EntityChangedEventData<ApiResource>>, |
|||
ILocalEventHandler<EntityChangedEventData<ApiScope>>, |
|||
ITransientDependency |
|||
{ |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
|
|||
public IdentityServerCacheItemInvalidator(IServiceProvider serviceProvider) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
} |
|||
|
|||
public virtual async Task HandleEventAsync(EntityChangedEventData<Client> eventData) |
|||
{ |
|||
var clientCache = ServiceProvider.GetRequiredService<IDistributedCache<IdentityServer4.Models.Client>>(); |
|||
await clientCache.RemoveAsync(eventData.Entity.ClientId); |
|||
|
|||
var corsCache = ServiceProvider.GetRequiredService<IDistributedCache<AllowedCorsOriginsCacheItem>>(); |
|||
await corsCache.RemoveAsync(AllowedCorsOriginsCacheItem.AllOrigins); |
|||
} |
|||
|
|||
public async Task HandleEventAsync(EntityChangedEventData<ClientCorsOrigin> eventData) |
|||
{ |
|||
var corsCache = ServiceProvider.GetRequiredService<IDistributedCache<AllowedCorsOriginsCacheItem>>(); |
|||
await corsCache.RemoveAsync(AllowedCorsOriginsCacheItem.AllOrigins); |
|||
} |
|||
|
|||
public virtual async Task HandleEventAsync(EntityChangedEventData<IdentityResource> eventData) |
|||
{ |
|||
var cache = ServiceProvider.GetRequiredService<IDistributedCache<IdentityServer4.Models.IdentityResource>>(); |
|||
await cache.RemoveAsync(eventData.Entity.Name); |
|||
|
|||
var resourcesCache = ServiceProvider.GetRequiredService<IDistributedCache<IdentityServer4.Models.Resources>>(); |
|||
await resourcesCache.RemoveAsync(ResourceStore.AllResourcesKey); |
|||
} |
|||
|
|||
public virtual async Task HandleEventAsync(EntityChangedEventData<ApiResource> eventData) |
|||
{ |
|||
var cache = ServiceProvider.GetRequiredService<IDistributedCache<IdentityServer4.Models.ApiResource>>(); |
|||
await cache.RemoveAsync(ResourceStore.ApiResourceNameCacheKeyPrefix + eventData.Entity.Name); |
|||
await cache.RemoveManyAsync(eventData.Entity.Scopes.Select(x => ResourceStore.ApiResourceScopeNameCacheKeyPrefix + x.Scope)); |
|||
|
|||
var resourcesCache = ServiceProvider.GetRequiredService<IDistributedCache<IdentityServer4.Models.Resources>>(); |
|||
await resourcesCache.RemoveAsync(ResourceStore.AllResourcesKey); |
|||
} |
|||
|
|||
public virtual async Task HandleEventAsync(EntityChangedEventData<ApiScope> eventData) |
|||
{ |
|||
var cache = ServiceProvider.GetRequiredService<IDistributedCache<IdentityServer4.Models.ApiScope>>(); |
|||
await cache.RemoveAsync(eventData.Entity.Name); |
|||
|
|||
var resourcesCache = ServiceProvider.GetRequiredService<IDistributedCache<IdentityServer4.Models.Resources>>(); |
|||
await resourcesCache.RemoveAsync(ResourceStore.AllResourcesKey); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,138 @@ |
|||
using System.Threading.Tasks; |
|||
using IdentityServer4.Models; |
|||
using IdentityServer4.Services; |
|||
using IdentityServer4.Stores; |
|||
using Shouldly; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.IdentityServer.ApiResources; |
|||
using Volo.Abp.IdentityServer.ApiScopes; |
|||
using Volo.Abp.IdentityServer.Clients; |
|||
using Volo.Abp.IdentityServer.IdentityResources; |
|||
using Xunit; |
|||
using ApiResource = IdentityServer4.Models.ApiResource; |
|||
using ApiScope = IdentityServer4.Models.ApiScope; |
|||
using Client = IdentityServer4.Models.Client; |
|||
using IdentityResource = IdentityServer4.Models.IdentityResource; |
|||
|
|||
namespace Volo.Abp.IdentityServer.Cache |
|||
{ |
|||
public class IdentityServerCacheItemInvalidator_Tests : AbpIdentityServerTestBase |
|||
{ |
|||
private readonly IClientStore _clientStore; |
|||
private readonly IResourceStore _resourceStore; |
|||
|
|||
private readonly IClientRepository _clientRepository; |
|||
private readonly IIdentityResourceRepository _identityResourceRepository; |
|||
private readonly IApiResourceRepository _apiResourceRepository; |
|||
private readonly IApiScopeRepository _apiScopeRepository; |
|||
|
|||
private readonly IDistributedCache<Client> _clientCache; |
|||
private readonly IDistributedCache<IdentityResource> _identityResourceCache; |
|||
private readonly IDistributedCache<ApiResource>_apiResourceCache; |
|||
private readonly IDistributedCache<ApiScope> _apiScopeCache; |
|||
private readonly IDistributedCache<Resources> _resourceCache; |
|||
|
|||
private readonly AbpIdentityServerTestData _testData; |
|||
|
|||
public IdentityServerCacheItemInvalidator_Tests() |
|||
{ |
|||
_clientStore = GetRequiredService<IClientStore>(); |
|||
_resourceStore = GetRequiredService<IResourceStore>(); |
|||
|
|||
_clientRepository = GetRequiredService<IClientRepository>(); |
|||
_identityResourceRepository = GetRequiredService<IIdentityResourceRepository>(); |
|||
_apiResourceRepository = GetRequiredService<IApiResourceRepository>(); |
|||
_apiScopeRepository = GetRequiredService<IApiScopeRepository>(); |
|||
|
|||
_clientCache = GetRequiredService<IDistributedCache<Client>>(); |
|||
_identityResourceCache = GetRequiredService<IDistributedCache<IdentityResource>>(); |
|||
_apiResourceCache = GetRequiredService<IDistributedCache<ApiResource>>(); |
|||
_apiScopeCache = GetRequiredService<IDistributedCache<ApiScope>>(); |
|||
_resourceCache = GetRequiredService<IDistributedCache<Resources>>(); |
|||
|
|||
_testData = GetRequiredService<AbpIdentityServerTestData>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Models_Should_Cached_And_Invalidator_When_Its_Changed() |
|||
{ |
|||
//client
|
|||
var clientId = "ClientId1"; |
|||
(await _clientCache.GetAsync(clientId)).ShouldBeNull(); |
|||
|
|||
var client = await _clientStore.FindClientByIdAsync(clientId); |
|||
client.ShouldNotBeNull(); |
|||
|
|||
var clientCacheItem = await _clientCache.GetAsync(clientId); |
|||
clientCacheItem.ShouldNotBeNull(); |
|||
|
|||
await _clientRepository.DeleteAsync(_testData.Client1Id); |
|||
(await _clientCache.GetAsync(clientId)).ShouldBeNull(); |
|||
|
|||
|
|||
//Api Resource
|
|||
var newApiResource1 = "NewApiResource1"; |
|||
var newApiResource2 = "NewApiResource2"; |
|||
var testApiResourceName1 = "Test-ApiResource-Name-1"; |
|||
var testApiResourceApiScopeName1 = "Test-ApiResource-ApiScope-Name-1"; |
|||
var newApiResources = new[] {newApiResource1, newApiResource2}; |
|||
|
|||
//FindApiResourcesByNameAsync
|
|||
(await _apiResourceCache.GetAsync(newApiResource1)).ShouldBeNull(); |
|||
(await _apiResourceCache.GetAsync(newApiResource2)).ShouldBeNull(); |
|||
await _resourceStore.FindApiResourcesByNameAsync(newApiResources); |
|||
(await _apiResourceCache.GetAsync(ResourceStore.ApiResourceNameCacheKeyPrefix + newApiResource1)).ShouldNotBeNull(); |
|||
(await _apiResourceCache.GetAsync(ResourceStore.ApiResourceNameCacheKeyPrefix + newApiResource2)).ShouldNotBeNull(); |
|||
|
|||
var apiResource1 = await _apiResourceRepository.FindByNameAsync(newApiResource1); |
|||
await _apiResourceRepository.DeleteAsync(apiResource1); |
|||
(await _apiResourceCache.GetAsync(newApiResource1)).ShouldBeNull(); |
|||
|
|||
var apiResource2 = await _apiResourceRepository.FindByNameAsync(newApiResource2); |
|||
await _apiResourceRepository.DeleteAsync(apiResource2); |
|||
(await _apiResourceCache.GetAsync(newApiResource2)).ShouldBeNull(); |
|||
|
|||
//FindApiResourcesByScopeNameAsync
|
|||
(await _apiResourceCache.GetAsync(ResourceStore.ApiResourceScopeNameCacheKeyPrefix + testApiResourceApiScopeName1)).ShouldBeNull(); |
|||
await _resourceStore.FindApiResourcesByScopeNameAsync(new []{ testApiResourceApiScopeName1 }); |
|||
(await _apiResourceCache.GetAsync(ResourceStore.ApiResourceScopeNameCacheKeyPrefix + testApiResourceApiScopeName1)).ShouldNotBeNull(); |
|||
|
|||
var testApiResource1 = await _apiResourceRepository.FindByNameAsync(testApiResourceName1); |
|||
await _apiResourceRepository.DeleteAsync(testApiResource1); |
|||
(await _apiResourceCache.GetAsync(ResourceStore.ApiResourceScopeNameCacheKeyPrefix + testApiResourceApiScopeName1)).ShouldBeNull(); |
|||
|
|||
|
|||
//Identity Resource
|
|||
var testIdentityResourceName = "Test-Identity-Resource-Name-1"; |
|||
var testIdentityResourceNames = new[] {testIdentityResourceName}; |
|||
(await _identityResourceCache.GetAsync(testIdentityResourceName)).ShouldBeNull(); |
|||
await _resourceStore.FindIdentityResourcesByScopeNameAsync(testIdentityResourceNames); |
|||
(await _identityResourceCache.GetAsync(testIdentityResourceName)).ShouldNotBeNull(); |
|||
|
|||
var testIdentityResource = await _identityResourceRepository.FindByNameAsync(testIdentityResourceName); |
|||
await _identityResourceRepository.DeleteAsync(testIdentityResource); |
|||
(await _identityResourceCache.GetAsync(testIdentityResourceName)).ShouldBeNull(); |
|||
|
|||
|
|||
//Api Scope
|
|||
var testApiScopeName = "Test-ApiScope-Name-1"; |
|||
var testApiScopeNames = new[] {testApiScopeName}; |
|||
(await _apiScopeCache.GetAsync(testApiScopeName)).ShouldBeNull(); |
|||
await _resourceStore.FindApiScopesByNameAsync(testApiScopeNames); |
|||
(await _apiScopeCache.GetAsync(testApiScopeName)).ShouldNotBeNull(); |
|||
|
|||
var testApiScope = await _apiScopeRepository.GetByNameAsync(testApiScopeName); |
|||
await _apiScopeRepository.DeleteAsync(testApiScope); |
|||
(await _apiScopeCache.GetAsync(testApiScopeName)).ShouldBeNull(); |
|||
|
|||
|
|||
//Resources
|
|||
(await _resourceCache.GetAsync(ResourceStore.AllResourcesKey)).ShouldBeNull(); |
|||
await _resourceStore.GetAllResourcesAsync(); |
|||
(await _resourceCache.GetAsync(ResourceStore.AllResourcesKey)).ShouldNotBeNull(); |
|||
|
|||
await _identityResourceRepository.DeleteAsync(_testData.IdentityResource1Id); |
|||
(await _resourceCache.GetAsync(ResourceStore.AllResourcesKey)).ShouldBeNull(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using IdentityServer4.Stores; |
|||
using Shouldly; |
|||
using Volo.Abp.IdentityServer.ApiResources; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.IdentityServer |
|||
{ |
|||
public class ResourceStore_Cache_Tests : AbpIdentityServerDomainTestBase |
|||
{ |
|||
private readonly IResourceStore _resourceStore; |
|||
|
|||
public ResourceStore_Cache_Tests() |
|||
{ |
|||
_resourceStore = GetRequiredService<IResourceStore>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task FindIdentityResourcesByScopeNameAsync() |
|||
{ |
|||
var identityResources = (await _resourceStore.FindIdentityResourcesByScopeNameAsync(new[] {"Test-Identity-Resource-Name-1"})).ToList(); |
|||
identityResources.ShouldNotBeEmpty(); |
|||
identityResources.Count.ShouldBe(1); |
|||
identityResources.First().Name.ShouldBe("Test-Identity-Resource-Name-1"); |
|||
|
|||
var identityResources2 = (await _resourceStore.FindIdentityResourcesByScopeNameAsync(new[] {"Test-Identity-Resource-Name-1", "NewIdentityResource1"})).ToList(); |
|||
identityResources2.ShouldNotBeEmpty(); |
|||
identityResources2.Count.ShouldBe(2); |
|||
identityResources2.ShouldContain(x => x.Name == "NewIdentityResource1"); |
|||
identityResources2.ShouldContain(x => x.Name == identityResources.First().Name); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task FindApiScopesByNameAsync() |
|||
{ |
|||
var apiScopes1 = (await _resourceStore.FindApiScopesByNameAsync(new[] {"Test-ApiScope-Name-1"})).ToList(); |
|||
apiScopes1.ShouldNotBeEmpty(); |
|||
apiScopes1.Count.ShouldBe(1); |
|||
apiScopes1.First().Name.ShouldBe("Test-ApiScope-Name-1"); |
|||
|
|||
var apiScopes2 = (await _resourceStore.FindApiScopesByNameAsync(new[] {"Test-ApiScope-Name-1", "Test-ApiScope-Name-2"})).ToList(); |
|||
apiScopes2.ShouldNotBeEmpty(); |
|||
apiScopes2.Count.ShouldBe(2); |
|||
apiScopes2.ShouldContain(x => x.Name == "Test-ApiScope-Name-1"); |
|||
apiScopes2.ShouldContain(x => x.Name == apiScopes1.First().Name); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task FindApiResourcesByScopeNameAsync() |
|||
{ |
|||
var apiResources1 = (await _resourceStore.FindApiResourcesByScopeNameAsync(new[] {"Test-ApiResource-ApiScope-Name-1"})).ToList(); |
|||
apiResources1.ShouldNotBeEmpty(); |
|||
apiResources1.Count.ShouldBe(1); |
|||
apiResources1.First().Name.ShouldBe("Test-ApiResource-Name-1"); |
|||
|
|||
var apiResources2 = (await _resourceStore.FindApiResourcesByScopeNameAsync(new[] {"Test-ApiResource-ApiScope-Name-1", nameof(ApiResourceScope.Scope)})).ToList(); |
|||
apiResources2.ShouldNotBeEmpty(); |
|||
apiResources2.Count.ShouldBe(2); |
|||
apiResources2.ShouldContain(x => x.Name == "Test-ApiResource-Name-1"); |
|||
apiResources2.ShouldContain(x => x.Name == apiResources1.First().Name); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task FindApiResourcesByNameAsync() |
|||
{ |
|||
var apiResources1 = (await _resourceStore.FindApiResourcesByNameAsync(new[] {"Test-ApiResource-Name-1"})).ToList(); |
|||
apiResources1.ShouldNotBeEmpty(); |
|||
apiResources1.Count.ShouldBe(1); |
|||
apiResources1.First().Name.ShouldBe("Test-ApiResource-Name-1"); |
|||
|
|||
var apiResources2 = (await _resourceStore.FindApiResourcesByNameAsync(new[] {"Test-ApiResource-Name-1", "NewApiResource1"})).ToList(); |
|||
apiResources2.ShouldNotBeEmpty(); |
|||
apiResources2.Count.ShouldBe(2); |
|||
apiResources2.ShouldContain(x => x.Name == "NewApiResource1"); |
|||
apiResources2.ShouldContain(x => x.Name == apiResources1.First().Name); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue