From 96f1446b9e6b68cea7656badd1ab3c2aad9e63b1 Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 13 Sep 2022 15:29:15 +0800 Subject: [PATCH] Cache a `scope` with multiple `ApiResource`. Fix #13982 --- .../Volo/Abp/IdentityServer/ResourceStore.cs | 29 ++++++++++++------- .../ResourceStore_Cache_Tests.cs | 6 ++-- .../AbpIdentityServerTestDataBuilder.cs | 1 + 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ResourceStore.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ResourceStore.cs index 51862d7597..f9988a377e 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ResourceStore.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ResourceStore.cs @@ -31,6 +31,7 @@ public class ResourceStore : IResourceStore protected IDistributedCache IdentityResourceCache { get; } protected IDistributedCache ApiScopeCache { get; } protected IDistributedCache ApiResourceCache { get; } + protected IDistributedCache> ApiResourcesCache { get; } protected IDistributedCache ResourcesCache { get; } protected IdentityServerOptions Options { get; } @@ -42,6 +43,7 @@ public class ResourceStore : IResourceStore IDistributedCache identityResourceCache, IDistributedCache apiScopeCache, IDistributedCache apiResourceCache, + IDistributedCache> apiResourcesCache, IDistributedCache resourcesCache, IOptions options) { @@ -52,6 +54,7 @@ public class ResourceStore : IResourceStore IdentityResourceCache = identityResourceCache; ApiScopeCache = apiScopeCache; ApiResourceCache = apiResourceCache; + ApiResourcesCache = apiResourcesCache; ResourcesCache = resourcesCache; Options = options.Value; } @@ -91,16 +94,22 @@ public class ResourceStore : IResourceStore /// public virtual async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames) { - return (await GetCacheItemsAsync( - ApiResourceCache, - scopeNames, - async keys => await ApiResourceRepository.GetListByScopesAsync(keys, includeDetails: true), - (models, cacheKeyPrefix) => - { - return models - .Select(model => model.Scopes.Select(scope => new KeyValuePair(AddCachePrefix(scope, cacheKeyPrefix), model)).ToList()) - .Where(scopes => scopes.Any()).Cast>>().ToList(); - }, ApiResourceScopeNameCacheKeyPrefix)).DistinctBy(x => x.Name); + var cacheItems = await ApiResourcesCache.GetManyAsync(AddCachePrefix(scopeNames, ApiResourceScopeNameCacheKeyPrefix)); + if (cacheItems.All(x => x.Value != null)) + { + return cacheItems.SelectMany(x => x.Value).DistinctBy(x => x.Name); + } + + var otherKeys = RemoveCachePrefix(cacheItems.Where(x => x.Value == null).Select(x => x.Key), ApiResourceScopeNameCacheKeyPrefix).ToArray(); + var otherModels = ObjectMapper.Map, List>(await ApiResourceRepository.GetListByScopesAsync(otherKeys, includeDetails: true)); + + var otherCacheItems = otherKeys.Select(otherKey => new KeyValuePair>(AddCachePrefix(otherKey, ApiResourceScopeNameCacheKeyPrefix), otherModels)).ToList(); + await ApiResourcesCache.SetManyAsync(otherCacheItems, new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = Options.Caching.ClientStoreExpiration + }); + + return cacheItems.Where(x => x.Value != null).SelectMany(x => x.Value).Concat(otherModels).DistinctBy(x => x.Name); } /// diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/ResourceStore_Cache_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/ResourceStore_Cache_Tests.cs index b33b8aa580..20b8ff8689 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/ResourceStore_Cache_Tests.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/ResourceStore_Cache_Tests.cs @@ -51,14 +51,14 @@ public class ResourceStore_Cache_Tests : AbpIdentityServerDomainTestBase { 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"); + apiResources1.Count.ShouldBe(2); + apiResources1.ShouldContain(x => x.Name == "Test-ApiResource-Name-1"); var apiResources2 = (await _resourceStore.FindApiResourcesByScopeNameAsync(new[] { "Test-ApiResource-ApiScope-Name-1", "Test-ApiResource-ApiScope-Name-2", 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); + apiResources2.ShouldContain(x => x.Name == "NewApiResource1"); } [Fact] diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs index eaf8aabf58..e6344f9c6f 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs @@ -87,6 +87,7 @@ public class AbpIdentityServerTestDataBuilder : ITransientDependency apiResource.DisplayName = nameof(apiResource.DisplayName); apiResource.AddScope(nameof(ApiResourceScope.Scope)); + apiResource.AddScope("Test-ApiResource-ApiScope-Name-1"); apiResource.AddUserClaim(nameof(ApiResourceClaim.Type)); apiResource.AddSecret(nameof(ApiResourceSecret.Value));