From 49d7941622ccd1d03160ee295355224ad0e12c6d Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 6 Apr 2022 15:33:08 +0800 Subject: [PATCH] Add Cache feature. --- .../app/OpenIddict.Demo.API/Program.cs | 4 - .../ServerDataSeedContributor.cs | 1 - .../OpenIddictServerModule.cs | 2 - .../Pages/Index.cshtml.cs | 3 +- .../AbpOpenIdDictControllerBase.cs | 1 - .../Controllers/AuthorizeController.cs | 1 - .../TokenController.AuthorizationCode.cs | 1 - .../OpenIddict/Controllers/TokenController.cs | 4 +- .../Controllers/UserInfoController.cs | 1 - .../Volo.Abp.OpenIddict.Domain.csproj | 1 + .../Abp/OpenIddict/AbpOpenIddictCacheBase.cs | 27 +++ .../OpenIddict/AbpOpenIddictDomainModule.cs | 29 ++- .../Abp/OpenIddict/AbpOpenIddictStoreBase.cs | 10 +- .../AbpOpenIddictApplicationCache.cs | 124 ++++++++++ .../AbpOpenIddictApplicationStore.cs | 221 ++++++------------ .../IOpenIddictApplicationRepository.cs | 7 - .../Applications/OpenIddictApplication.cs | 9 + .../OpenIddictApplicationExtensions.cs | 68 ++++++ .../OpenIddictApplicationModel.cs | 74 ++++++ .../AbpOpenIddictAuthorizationCache.cs | 182 +++++++++++++++ .../AbpOpenIddictAuthorizationStore.cs | 149 +++++------- .../IOpenIddictAuthorizationRepository.cs | 7 - .../Authorizations/OpenIddictAuthorization.cs | 9 + .../OpenIddictAuthorizationExtensions.cs | 56 +++++ .../OpenIddictAuthorizationModel.cs | 47 ++++ .../Scopes/AbpOpenIddictScopeCache.cs | 111 +++++++++ .../Scopes/AbpOpenIddictScopeStore.cs | 169 +++++--------- .../Scopes/IOpenIddictScopeRepository.cs | 7 - .../Abp/OpenIddict/Scopes/OpenIddictScope.cs | 9 + .../Scopes/OpenIddictScopeExtensions.cs | 56 +++++ .../OpenIddict/Scopes/OpenIddictScopeModel.cs | 50 ++++ .../Tokens/AbpOpenIddictTokenCache.cs | 210 +++++++++++++++++ .../Tokens/AbpOpenIddictTokenStore.cs | 152 ++++++------ .../Tokens/IOpenIddictTokenRepository.cs | 7 - .../Abp/OpenIddict/Tokens/OpenIddictToken.cs | 9 + .../Tokens/OpenIddictTokenExtensions.cs | 68 ++++++ .../OpenIddict/Tokens/OpenIddictTokenModel.cs | 71 ++++++ .../EfCoreOpenIddictApplicationRepository.cs | 21 +- ...EfCoreOpenIddictAuthorizationRepository.cs | 17 -- ...nIddictDbContextModelCreatingExtensions.cs | 1 - .../Scopes/EfCoreOpenIddictScopeRepository.cs | 15 -- .../Tokens/EfCoreOpenIddictTokenRepository.cs | 15 -- .../MongoOpenIddictApplicationRepository.cs | 12 - .../MongoOpenIddictAuthorizationRepository.cs | 15 -- .../Scopes/MongoOpenIddictScopeRepository.cs | 15 -- .../Tokens/MongoOpenIddictTokenRepository.cs | 15 -- .../OpenIddictTestBase.cs | 1 - .../OpenIddictTestBaseModule.cs | 1 - 48 files changed, 1468 insertions(+), 617 deletions(-) create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictCacheBase.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationCache.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationExtensions.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationModel.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationCache.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationExtensions.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationModel.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeCache.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeExtensions.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeModel.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenCache.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenExtensions.cs create mode 100644 modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenModel.cs diff --git a/modules/openiddict/app/OpenIddict.Demo.API/Program.cs b/modules/openiddict/app/OpenIddict.Demo.API/Program.cs index eb6516c44c..6218c5b9f7 100644 --- a/modules/openiddict/app/OpenIddict.Demo.API/Program.cs +++ b/modules/openiddict/app/OpenIddict.Demo.API/Program.cs @@ -1,9 +1,5 @@ using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; var builder = WebApplication.CreateBuilder(args); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs b/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs index feaae5106c..bd94e16f9e 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs @@ -1,6 +1,5 @@ using System.Globalization; using OpenIddict.Abstractions; -using Volo; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs b/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs index 3efe112ab2..cbcf45e457 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs @@ -1,8 +1,6 @@ using System.Text; -using Microsoft.AspNetCore.Authentication; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; -using OpenIddict.Abstractions; using OpenIddict.Demo.Server.EntityFrameworkCore; using Volo.Abp; using Volo.Abp.Account; diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Pages/Index.cshtml.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Pages/Index.cshtml.cs index f1cf22325b..8ea6d7fa80 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Pages/Index.cshtml.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Pages/Index.cshtml.cs @@ -1,5 +1,4 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Mvc.RazorPages; namespace OpenIddict.Demo.Server.Pages; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AbpOpenIdDictControllerBase.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AbpOpenIdDictControllerBase.cs index 055428093b..a658181077 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AbpOpenIdDictControllerBase.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AbpOpenIdDictControllerBase.cs @@ -13,7 +13,6 @@ using OpenIddict.Abstractions; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Identity; using Volo.Abp.OpenIddict.Localization; -using Volo.Abp.Security.Claims; using IdentityUser = Volo.Abp.Identity.IdentityUser; namespace Volo.Abp.OpenIddict.Controllers; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs index a3cf2ccb64..094a65e228 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.AuthorizationCode.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.AuthorizationCode.cs index 1ca6263888..07f7e52070 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.AuthorizationCode.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.AuthorizationCode.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.cs index 364cce5f62..b5a8b41327 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.cs @@ -1,6 +1,4 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using OpenIddict.Abstractions; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/UserInfoController.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/UserInfoController.cs index 7ad74e2c25..2f31dbd625 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/UserInfoController.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/UserInfoController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj index 18c0de1590..3881808934 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj @@ -10,6 +10,7 @@ + diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictCacheBase.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictCacheBase.cs new file mode 100644 index 0000000000..43d373ba2c --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictCacheBase.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Caching; + +namespace Volo.Abp.OpenIddict; + +public class AbpOpenIddictCacheBase + where TModel : class + where TEntity : class +{ + public ILogger> Logger { get; set; } + + protected IDistributedCache Cache { get; } + + protected IDistributedCache ArrayCache { get; } + + protected TStore Store { get; } + + protected AbpOpenIddictCacheBase(IDistributedCache cache, IDistributedCache arrayCache, TStore store) + { + Cache = cache; + ArrayCache = arrayCache; + Store = store; + + Logger = NullLogger>.Instance; + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs index 0c3ec3b11b..6c9a679888 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs @@ -2,9 +2,10 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; -using OpenIddict.Core; using Volo.Abp.BackgroundWorkers; +using Volo.Abp.Caching; using Volo.Abp.Domain; +using Volo.Abp.Guids; using Volo.Abp.Identity; using Volo.Abp.Modularity; using Volo.Abp.OpenIddict.Applications; @@ -19,7 +20,9 @@ namespace Volo.Abp.OpenIddict; [DependsOn( typeof(AbpDddDomainModule), typeof(AbpIdentityDomainModule), - typeof(AbpOpenIddictDomainSharedModule) + typeof(AbpOpenIddictDomainSharedModule), + typeof(AbpCachingModule), + typeof(AbpGuidsModule) )] public class AbpOpenIddictDomainModule : AbpModule { @@ -65,12 +68,16 @@ public class AbpOpenIddictDomainModule : AbpModule .AddCore(builder => { builder - .SetDefaultApplicationEntity() - .SetDefaultAuthorizationEntity() - .SetDefaultScopeEntity() - .SetDefaultTokenEntity(); + .SetDefaultApplicationEntity() + .SetDefaultAuthorizationEntity() + .SetDefaultScopeEntity() + .SetDefaultTokenEntity(); - builder.DisableEntityCaching(); + builder + .AddApplicationStore() + .AddAuthorizationStore() + .AddScopeStore() + .AddTokenStore(); services.ExecutePreConfiguredActions(builder); }) @@ -122,14 +129,6 @@ public class AbpOpenIddictDomainModule : AbpModule services.ExecutePreConfiguredActions(builder); }); - services.Configure(options => - { - options.DefaultApplicationType = typeof(OpenIddictApplication); - options.DefaultAuthorizationType = typeof(OpenIddictAuthorization); - options.DefaultScopeType = typeof(OpenIddictScope); - options.DefaultTokenType = typeof(OpenIddictToken); - }); - services.ExecutePreConfiguredActions(openIddictBuilder); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictStoreBase.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictStoreBase.cs index 9483471614..4602766f7e 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictStoreBase.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictStoreBase.cs @@ -4,10 +4,10 @@ using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Domain.Repositories; +using Volo.Abp.Guids; using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict; @@ -19,13 +19,13 @@ public abstract class AbpOpenIddictStoreBase protected TRepository Repository { get; } protected IUnitOfWorkManager UnitOfWorkManager { get; } - protected IMemoryCache Cache { get; } + protected IGuidGenerator GuidGenerator { get; } - protected AbpOpenIddictStoreBase(TRepository repository, IUnitOfWorkManager unitOfWorkManager, IMemoryCache cache) + protected AbpOpenIddictStoreBase(TRepository repository, IUnitOfWorkManager unitOfWorkManager, IGuidGenerator guidGenerator) { Repository = repository; UnitOfWorkManager = unitOfWorkManager; - Cache = cache; + GuidGenerator = guidGenerator; Logger = NullLogger>.Instance; } @@ -40,6 +40,8 @@ public abstract class AbpOpenIddictStoreBase return identifier.ToString("D"); } + + protected virtual string WriteStream(Action action) { using (var stream = new MemoryStream()) diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationCache.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationCache.cs new file mode 100644 index 0000000000..2a1e49f4f7 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationCache.cs @@ -0,0 +1,124 @@ +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using OpenIddict.Abstractions; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.OpenIddict.Applications; + +public class AbpOpenIddictApplicationCache : AbpOpenIddictCacheBase>, + IOpenIddictApplicationCache, + ITransientDependency +{ + public AbpOpenIddictApplicationCache( + IDistributedCache cache, + IDistributedCache arrayCache, + IOpenIddictApplicationStore store) + : base(cache, arrayCache, store) + { + } + + public virtual async ValueTask AddAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) + { + Check.NotNull(application, nameof(application)); + + await RemoveAsync(application, cancellationToken); + + await Cache.SetManyAsync(new List> + { + new KeyValuePair($"{nameof(FindByClientIdAsync)}_{await Store.GetClientIdAsync(application, cancellationToken)}", application), + new KeyValuePair($"{nameof(FindByIdAsync)}_{await Store.GetIdAsync(application, cancellationToken)}", application) + }, token: cancellationToken); + } + + public virtual async ValueTask FindByClientIdAsync(string identifier, CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + return await Cache.GetOrAddAsync($"{nameof(FindByClientIdAsync)}_{identifier}", async () => + { + var application = await Store.FindByClientIdAsync(identifier, cancellationToken); + if (application != null) + { + await AddAsync(application, cancellationToken); + } + return application; + }, token: cancellationToken); + } + + public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + return await Cache.GetOrAddAsync($"{nameof(FindByIdAsync)}_{identifier}", async () => + { + var application = await Store.FindByIdAsync(identifier, cancellationToken); + if (application != null) + { + await AddAsync(application, cancellationToken); + } + return application; + }, token: cancellationToken); + } + + public virtual async IAsyncEnumerable FindByPostLogoutRedirectUriAsync(string address, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(address, nameof(address)); + + var applications = await ArrayCache.GetOrAddAsync($"{nameof(FindByPostLogoutRedirectUriAsync)}_{address}", async () => + { + var applications = new List(); + await foreach (var application in Store.FindByPostLogoutRedirectUriAsync(address, cancellationToken)) + { + applications.Add(application); + await AddAsync(application, cancellationToken); + } + return applications.ToArray(); + + }, token: cancellationToken); + + foreach (var application in applications) + { + yield return application; + } + } + + public virtual async IAsyncEnumerable FindByRedirectUriAsync(string address, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(address, nameof(address)); + + var applications = await ArrayCache.GetOrAddAsync($"{nameof(FindByRedirectUriAsync)}_{address}", async () => + { + var applications = new List(); + await foreach (var application in Store.FindByRedirectUriAsync(address, cancellationToken)) + { + applications.Add(application); + await AddAsync(application, cancellationToken); + } + return applications.ToArray(); + + }, token: cancellationToken); + + foreach (var application in applications) + { + yield return application; + } + } + + public virtual async ValueTask RemoveAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) + { + Check.NotNull(application, nameof(application)); + + await Cache.RemoveAsync($"{nameof(FindByClientIdAsync)}_{await Store.GetClientIdAsync(application, cancellationToken)}", token: cancellationToken); + await Cache.RemoveAsync($"{nameof(FindByIdAsync)}_{await Store.GetIdAsync(application, cancellationToken)}", token: cancellationToken); + + var redirectUris = await Store.GetRedirectUrisAsync(application, cancellationToken); + await ArrayCache.RemoveManyAsync(redirectUris.Select(address => $"{nameof(FindByRedirectUriAsync)}_{address}").ToArray(), token: cancellationToken); + + var postLogoutRedirectUris = await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken); + await ArrayCache.RemoveManyAsync(postLogoutRedirectUris.Select(address => $"{nameof(FindByPostLogoutRedirectUriAsync)}_{address}").ToArray(), token: cancellationToken); + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs index 0205238cfc..cdc69cde8d 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs @@ -8,24 +8,23 @@ using System.Runtime.CompilerServices; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; using OpenIddict.Abstractions; -using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; using Volo.Abp.OpenIddict.Tokens; using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict.Applications; -public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase, IOpenIddictApplicationStore, IScopedDependency +public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase, IOpenIddictApplicationStore { protected IOpenIddictTokenRepository TokenRepository { get; } public AbpOpenIddictApplicationStore( IOpenIddictApplicationRepository repository, IUnitOfWorkManager unitOfWorkManager, - IMemoryCache cache, - IOpenIddictTokenRepository tokenRepository) - : base(repository, unitOfWorkManager, cache) + IOpenIddictTokenRepository tokenRepository, + IGuidGenerator guidGenerator) + : base(repository, unitOfWorkManager, guidGenerator) { TokenRepository = tokenRepository; } @@ -35,21 +34,19 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) + public ValueTask CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - return await Repository.CountAsync(query, cancellationToken); + throw new NotSupportedException(); } - public async ValueTask CreateAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public async ValueTask CreateAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); - await Repository.InsertAsync(application, autoSave: true, cancellationToken: cancellationToken); + await Repository.InsertAsync(application.ToEntity(), autoSave: true, cancellationToken: cancellationToken); } - public async ValueTask DeleteAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public async ValueTask DeleteAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -57,27 +54,27 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase FindByIdAsync(string identifier, CancellationToken cancellationToken) + public async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); - return await Repository.FindAsync(ConvertIdentifierFromString(identifier), cancellationToken: cancellationToken); + return (await Repository.FindAsync(ConvertIdentifierFromString(identifier), cancellationToken: cancellationToken)).ToModel(); } - public async ValueTask FindByClientIdAsync(string identifier, CancellationToken cancellationToken) + public async ValueTask FindByClientIdAsync(string identifier, CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); - return await Repository.FindByClientIdAsync(identifier, cancellationToken: cancellationToken); + return (await Repository.FindByClientIdAsync(identifier, cancellationToken: cancellationToken)).ToModel(); } - public async IAsyncEnumerable FindByPostLogoutRedirectUriAsync(string address, [EnumeratorCancellation] CancellationToken cancellationToken) + public async IAsyncEnumerable FindByPostLogoutRedirectUriAsync(string address, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(address, nameof(address)); @@ -85,71 +82,69 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase FindByRedirectUriAsync(string address, [EnumeratorCancellation] CancellationToken cancellationToken) + public async IAsyncEnumerable FindByRedirectUriAsync(string address, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(address, nameof(address)); var applications = await Repository.FindByRedirectUriAsync(address, cancellationToken); foreach (var application in applications) { - var addresses = await GetRedirectUrisAsync(application, cancellationToken); + var addresses = await GetRedirectUrisAsync(application.ToModel(), cancellationToken); if (addresses.Contains(address, StringComparer.Ordinal)) { - yield return application; + yield return application.ToModel(); } } } - public async ValueTask GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + public ValueTask GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - return await Repository.GetAsync(query, state, cancellationToken); + throw new NotSupportedException(); } - public ValueTask GetClientIdAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask GetClientIdAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); return new ValueTask(application.ClientId); } - public ValueTask GetClientSecretAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask GetClientSecretAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); return new ValueTask(application.ClientSecret); } - public ValueTask GetClientTypeAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask GetClientTypeAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); return new ValueTask(application.Type); } - public ValueTask GetConsentTypeAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask GetConsentTypeAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); return new ValueTask(application.ConsentType); } - public ValueTask GetDisplayNameAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask GetDisplayNameAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); return new ValueTask(application.DisplayName); } - public ValueTask> GetDisplayNamesAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask> GetDisplayNamesAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -158,15 +153,8 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(ImmutableDictionary.Create()); } - // Note: parsing the stringified display names is an expensive operation. - // To mitigate that, the resulting object is stored in the memory cache. - var key = string.Concat("7762c378-c113-4564-b14b-1402b3949aaa", "\x1e", application.DisplayNames); - var names = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(application.DisplayNames)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(application.DisplayNames); var builder = ImmutableDictionary.CreateBuilder(); foreach (var property in document.RootElement.EnumerateObject()) @@ -180,20 +168,18 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(names); + return new ValueTask>(builder.ToImmutable()); + } } - public ValueTask GetIdAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask GetIdAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); return new ValueTask(ConvertIdentifierToString(application.Id)); } - public ValueTask> GetPermissionsAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask> GetPermissionsAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -202,15 +188,8 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(ImmutableArray.Create()); } - // Note: parsing the stringified permissions is an expensive operation. - // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat("0347e0aa-3a26-410a-97e8-a83bdeb21a1f", "\x1e", application.Permissions); - var permissions = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(application.Permissions)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(application.Permissions); var builder = ImmutableArray.CreateBuilder(document.RootElement.GetArrayLength()); foreach (var element in document.RootElement.EnumerateArray()) @@ -224,13 +203,11 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(permissions); + return new ValueTask>(builder.ToImmutable()); + } } - public ValueTask> GetPostLogoutRedirectUrisAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask> GetPostLogoutRedirectUrisAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -239,15 +216,8 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(ImmutableArray.Create()); } - // Note: parsing the stringified addresses is an expensive operation. - // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat("fb14dfb9-9216-4b77-bfa9-7e85f8201ff4", "\x1e", application.PostLogoutRedirectUris); - var addresses = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(application.PostLogoutRedirectUris)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(application.PostLogoutRedirectUris); var builder = ImmutableArray.CreateBuilder(document.RootElement.GetArrayLength()); foreach (var element in document.RootElement.EnumerateArray()) @@ -261,13 +231,11 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(addresses); + return new ValueTask>(builder.ToImmutable()); + }; } - public ValueTask> GetPropertiesAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask> GetPropertiesAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -276,29 +244,19 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(ImmutableDictionary.Create()); } - // Note: parsing the stringified properties is an expensive operation. - // To mitigate that, the resulting object is stored in the memory cache. - var key = string.Concat("2e3e9680-5654-48d8-a27d-b8bb4f0f1d50", "\x1e", application.Properties); - var properties = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(application.Properties)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(application.Properties); var builder = ImmutableDictionary.CreateBuilder(); foreach (var property in document.RootElement.EnumerateObject()) { builder[property.Name] = property.Value.Clone(); } - - return builder.ToImmutable(); - }); - - return new ValueTask>(properties); + return new ValueTask>(builder.ToImmutable()); + } } - public ValueTask> GetRedirectUrisAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask> GetRedirectUrisAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -307,15 +265,8 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(ImmutableArray.Create()); } - // Note: parsing the stringified addresses is an expensive operation. - // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat("851d6f08-2ee0-4452-bbe5-ab864611ecaa", "\x1e", application.RedirectUris); - var addresses = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(application.RedirectUris)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(application.RedirectUris); var builder = ImmutableArray.CreateBuilder(document.RootElement.GetArrayLength()); foreach (var element in document.RootElement.EnumerateArray()) @@ -329,13 +280,11 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(addresses); + return new ValueTask>( builder.ToImmutable()); + } } - public ValueTask> GetRequirementsAsync(OpenIddictApplication application, CancellationToken cancellationToken) + public ValueTask> GetRequirementsAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -344,15 +293,8 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(ImmutableArray.Create()); } - // Note: parsing the stringified requirements is an expensive operation. - // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat("b4808a89-8969-4512-895f-a909c62a8995", "\x1e", application.Requirements); - var requirements = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(application.Requirements)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(application.Requirements); var builder = ImmutableArray.CreateBuilder(document.RootElement.GetArrayLength()); foreach (var element in document.RootElement.EnumerateArray()) @@ -366,45 +308,33 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase>(requirements); + return new ValueTask>(builder.ToImmutable()); + } } - public ValueTask InstantiateAsync(CancellationToken cancellationToken) + public ValueTask InstantiateAsync(CancellationToken cancellationToken) { - try - { - return new ValueTask(Activator.CreateInstance()); - } - catch (MemberAccessException exception) + return new ValueTask(new OpenIddictApplicationModel { - return new ValueTask(Task.FromException(exception)); - } + Id = GuidGenerator.Create() + }); } - public async IAsyncEnumerable ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) + public async IAsyncEnumerable ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) { var applications = await Repository.ListAsync(count, offset, cancellationToken); foreach (var application in applications) { - yield return application; + yield return application.ToModel(); } } - public async IAsyncEnumerable ListAsync(Func, TState, IQueryable> query, TState state, [EnumeratorCancellation] CancellationToken cancellationToken) + public IAsyncEnumerable ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - var applications = await Repository.ListAsync(query, state, cancellationToken); - foreach (var application in applications) - { - yield return application; - } + throw new NotSupportedException(); } - public virtual ValueTask SetClientIdAsync(OpenIddictApplication application, string identifier, CancellationToken cancellationToken) + public virtual ValueTask SetClientIdAsync(OpenIddictApplicationModel application, string identifier, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -412,7 +342,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase names, - CancellationToken cancellationToken) + public virtual ValueTask SetDisplayNamesAsync(OpenIddictApplicationModel application, ImmutableDictionary names, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -469,7 +398,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase permissions, + public virtual ValueTask SetPermissionsAsync(OpenIddictApplicationModel application, ImmutableArray permissions, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -493,7 +422,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase addresses, + public virtual ValueTask SetPostLogoutRedirectUrisAsync(OpenIddictApplicationModel application, ImmutableArray addresses, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -517,7 +446,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase properties, + public virtual ValueTask SetPropertiesAsync(OpenIddictApplicationModel application, ImmutableDictionary properties, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -542,7 +471,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase addresses, + public virtual ValueTask SetRedirectUrisAsync(OpenIddictApplicationModel application, ImmutableArray addresses, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -566,7 +495,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase requirements, + public virtual ValueTask SetRequirementsAsync(OpenIddictApplicationModel application, ImmutableArray requirements, CancellationToken cancellationToken) { Check.NotNull(application, nameof(application)); @@ -590,10 +519,12 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase { - Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default); - Task FindByClientIdAsync(string clientId, CancellationToken cancellationToken = default); Task> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken = default); Task> FindByRedirectUriAsync(string address, CancellationToken cancellationToken = default); - Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default); - - Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplication.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplication.cs index fc477a4714..6ef1fea798 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplication.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplication.cs @@ -5,6 +5,15 @@ namespace Volo.Abp.OpenIddict.Applications; public class OpenIddictApplication : FullAuditedAggregateRoot { + public OpenIddictApplication() + { + } + + public OpenIddictApplication(Guid id) + : base(id) + { + } + /// /// Gets or sets the client identifier associated with the current application. /// diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationExtensions.cs new file mode 100644 index 0000000000..a0dcb9523f --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationExtensions.cs @@ -0,0 +1,68 @@ +namespace Volo.Abp.OpenIddict.Applications; + +public static class OpenIddictApplicationExtensions +{ + public static OpenIddictApplication ToEntity(this OpenIddictApplicationModel model) + { + Check.NotNull(model, nameof(model)); + + return new OpenIddictApplication(model.Id) + { + ClientId = model.ClientId, + ClientSecret = model.ClientSecret, + ConsentType = model.ConsentType, + DisplayName = model.DisplayName, + DisplayNames = model.DisplayNames, + Permissions = model.Permissions, + PostLogoutRedirectUris = model.PostLogoutRedirectUris, + Properties = model.Properties, + RedirectUris = model.RedirectUris, + Requirements = model.Requirements, + Type = model.Type + }; + } + + public static OpenIddictApplication ToEntity(this OpenIddictApplicationModel model, OpenIddictApplication entity) + { + Check.NotNull(model, nameof(model)); + Check.NotNull(entity, nameof(entity)); + + entity.ClientId = model.ClientId; + entity.ClientSecret = model.ClientSecret; + entity.ConsentType = model.ConsentType; + entity.DisplayName = model.DisplayName; + entity.DisplayNames = model.DisplayNames; + entity.Permissions = model.Permissions; + entity.PostLogoutRedirectUris = model.PostLogoutRedirectUris; + entity.Properties = model.Properties; + entity.RedirectUris = model.RedirectUris; + entity.Requirements = model.Requirements; + entity.Type = model.Type; + + return entity; + } + + public static OpenIddictApplicationModel ToModel(this OpenIddictApplication model) + { + if(model == null) + { + return null; + } + + return new OpenIddictApplicationModel + { + Id = model.Id, + ClientId = model.ClientId, + ClientSecret = model.ClientSecret, + ConsentType = model.ConsentType, + DisplayName = model.DisplayName, + DisplayNames = model.DisplayNames, + Permissions = model.Permissions, + PostLogoutRedirectUris = model.PostLogoutRedirectUris, + Properties = model.Properties, + RedirectUris = model.RedirectUris, + Requirements = model.Requirements, + Type = model.Type + }; + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationModel.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationModel.cs new file mode 100644 index 0000000000..3f08a4df6f --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationModel.cs @@ -0,0 +1,74 @@ +using System; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.OpenIddict.Applications; + +[Serializable, IgnoreMultiTenancy] +public class OpenIddictApplicationModel +{ + public Guid Id { get; set; } + + /// + /// Gets or sets the client identifier associated with the current application. + /// + public virtual string ClientId { get; set; } + + /// + /// Gets or sets the client secret associated with the current application. + /// Note: depending on the application manager used to create this instance, + /// this property may be hashed or encrypted for security reasons. + /// + public virtual string ClientSecret { get; set; } + + /// + /// Gets or sets the consent type associated with the current application. + /// + public virtual string ConsentType { get; set; } + + /// + /// Gets or sets the display name associated with the current application. + /// + public virtual string DisplayName { get; set; } + + /// + /// Gets or sets the localized display names + /// associated with the current application, + /// serialized as a JSON object. + /// + public virtual string DisplayNames { get; set; } + + /// + /// Gets or sets the permissions associated with the + /// current application, serialized as a JSON array. + /// + public virtual string Permissions { get; set; } + + /// + /// Gets or sets the logout callback URLs associated with + /// the current application, serialized as a JSON array. + /// + public virtual string PostLogoutRedirectUris { get; set; } + + /// + /// Gets or sets the additional properties serialized as a JSON object, + /// or null if no bag was associated with the current application. + /// + public virtual string Properties { get; set; } + + /// + /// Gets or sets the callback URLs associated with the + /// current application, serialized as a JSON array. + /// + public virtual string RedirectUris { get; set; } + + /// + /// Gets or sets the requirements associated with the + /// current application, serialized as a JSON array. + /// + public virtual string Requirements { get; set; } + + /// + /// Gets or sets the application type associated with the current application. + /// + public virtual string Type { get; set; } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationCache.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationCache.cs new file mode 100644 index 0000000000..9079a57acc --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationCache.cs @@ -0,0 +1,182 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using OpenIddict.Abstractions; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.OpenIddict.Authorizations; + +public class AbpOpenIddictAuthorizationCache : AbpOpenIddictCacheBase>, + IOpenIddictAuthorizationCache, + ITransientDependency +{ + public AbpOpenIddictAuthorizationCache( + IDistributedCache cache, + IDistributedCache arrayCache, + IOpenIddictAuthorizationStore store) + : base(cache, arrayCache, store) + { + } + + public async ValueTask AddAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) + { + Check.NotNull(authorization, nameof(authorization)); + + await RemoveAsync(authorization, cancellationToken); + + await Cache.SetAsync($"{nameof(FindByIdAsync)}_{await Store.GetIdAsync(authorization, cancellationToken)}", authorization, token: cancellationToken); + } + + public async IAsyncEnumerable FindAsync(string subject, string client, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + Check.NotNullOrEmpty(client, nameof(client)); + + var authorizations = await ArrayCache.GetOrAddAsync($"{nameof(FindAsync)}_{subject}_{client}", async () => + { + var applications = new List(); + await foreach (var authorization in Store.FindAsync(subject, client, cancellationToken)) + { + applications.Add(authorization); + await AddAsync(authorization, cancellationToken); + } + return applications.ToArray(); + }, token: cancellationToken); + + foreach (var authorization in authorizations) + { + yield return authorization; + } + } + + public async IAsyncEnumerable FindAsync(string subject, string client, string status, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + Check.NotNullOrEmpty(client, nameof(client)); + Check.NotNullOrEmpty(status, nameof(status)); + + var authorizations = await ArrayCache.GetOrAddAsync($"{nameof(FindAsync)}_{subject}_{client}_{status}", async () => + { + var applications = new List(); + await foreach (var authorization in Store.FindAsync(subject, client, status, cancellationToken)) + { + applications.Add(authorization); + await AddAsync(authorization, cancellationToken); + } + return applications.ToArray(); + }, token: cancellationToken); + + foreach (var authorization in authorizations) + { + yield return authorization; + } + } + + public async IAsyncEnumerable FindAsync(string subject, string client, string status, string type, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + Check.NotNullOrEmpty(client, nameof(client)); + Check.NotNullOrEmpty(status, nameof(status)); + Check.NotNullOrEmpty(type, nameof(type)); + + var authorizations = await ArrayCache.GetOrAddAsync($"{nameof(FindAsync)}_{subject}_{client}_{status}_{type}", async () => + { + var applications = new List(); + await foreach (var authorization in Store.FindAsync(subject, client, status, type, cancellationToken)) + { + applications.Add(authorization); + await AddAsync(authorization, cancellationToken); + } + return applications.ToArray(); + }, token: cancellationToken); + + foreach (var authorization in authorizations) + { + yield return authorization; + } + } + + public async IAsyncEnumerable FindAsync(string subject, string client, string status, string type, ImmutableArray scopes, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + Check.NotNullOrEmpty(client, nameof(client)); + Check.NotNullOrEmpty(status, nameof(status)); + Check.NotNullOrEmpty(type, nameof(type)); + + // Note: this method is only partially cached. + await foreach (var authorization in Store.FindAsync(subject, client, status, type, scopes, cancellationToken)) + { + await AddAsync(authorization, cancellationToken); + yield return authorization; + } + } + + public async IAsyncEnumerable FindByApplicationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + var authorizations = await ArrayCache.GetOrAddAsync($"{nameof(FindByApplicationIdAsync)}_{identifier}", async () => + { + var applications = new List(); + await foreach (var authorization in Store.FindByApplicationIdAsync(identifier, cancellationToken)) + { + applications.Add(authorization); + await AddAsync(authorization, cancellationToken); + } + return applications.ToArray(); + }, token: cancellationToken); + + foreach (var authorization in authorizations) + { + yield return authorization; + } + } + + public async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + return await Cache.GetOrAddAsync($"{nameof(FindByIdAsync)}_{identifier}", + async () => await Store.FindByIdAsync(identifier, cancellationToken), token: cancellationToken); + } + + public async IAsyncEnumerable FindBySubjectAsync(string subject, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + + var authorizations = await ArrayCache.GetOrAddAsync($"{nameof(FindBySubjectAsync)}_{subject}", async () => + { + var applications = new List(); + await foreach (var authorization in Store.FindBySubjectAsync(subject, cancellationToken)) + { + applications.Add(authorization); + await AddAsync(authorization, cancellationToken); + } + return applications.ToArray(); + }, token: cancellationToken); + + foreach (var authorization in authorizations) + { + yield return authorization; + } + } + + public virtual async ValueTask RemoveAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) + { + Check.NotNull(authorization, nameof(authorization)); + + await ArrayCache.RemoveManyAsync(new[] + { + $"{nameof(FindAsync)}_{await Store.GetSubjectAsync(authorization, cancellationToken)}_{await Store.GetApplicationIdAsync(authorization, cancellationToken)}", + $"{nameof(FindAsync)}_{await Store.GetSubjectAsync(authorization, cancellationToken)}_{await Store.GetApplicationIdAsync(authorization, cancellationToken)}_{await Store.GetStatusAsync(authorization, cancellationToken)}", + $"{nameof(FindAsync)}_{await Store.GetSubjectAsync(authorization, cancellationToken)}_{await Store.GetApplicationIdAsync(authorization, cancellationToken)}_{await Store.GetStatusAsync(authorization, cancellationToken)}_{await Store.GetTypeAsync(authorization, cancellationToken)}", + $"{nameof(FindByApplicationIdAsync)}_{await Store.GetApplicationIdAsync(authorization, cancellationToken)}", + $"{nameof(FindBySubjectAsync)}_{await Store.GetSubjectAsync(authorization, cancellationToken)}" + }, token: cancellationToken); + + await Cache.RemoveAsync($"{nameof(FindByIdAsync)}_{await Store.GetIdAsync(authorization, cancellationToken)}", token: cancellationToken); + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs index dfd67a8877..6c7db0c5c6 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs @@ -7,16 +7,15 @@ using System.Runtime.CompilerServices; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; using OpenIddict.Abstractions; -using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; using Volo.Abp.OpenIddict.Applications; using Volo.Abp.OpenIddict.Tokens; using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict.Authorizations; -public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase, IOpenIddictAuthorizationStore, IScopedDependency +public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase, IOpenIddictAuthorizationStore { protected IOpenIddictApplicationRepository ApplicationRepository { get; } protected IOpenIddictTokenRepository TokenRepository { get; } @@ -24,10 +23,10 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) + public virtual ValueTask CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - return await Repository.CountAsync(query, cancellationToken); + throw new NotSupportedException(); } - public virtual async ValueTask CreateAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual async ValueTask CreateAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); - await Repository.InsertAsync(authorization, autoSave: true, cancellationToken: cancellationToken); + await Repository.InsertAsync(authorization.ToEntity(), autoSave: true, cancellationToken: cancellationToken); } - public virtual async ValueTask DeleteAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual async ValueTask DeleteAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); @@ -60,13 +57,13 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase FindAsync(string subject, string client, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindAsync(string subject, string client, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); Check.NotNullOrEmpty(client, nameof(client)); @@ -74,11 +71,11 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase FindAsync(string subject, string client, string status, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindAsync(string subject, string client, string status, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); Check.NotNullOrEmpty(client, nameof(client)); @@ -87,11 +84,11 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase FindAsync(string subject, string client, string status, string type, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindAsync(string subject, string client, string status, string type, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); Check.NotNullOrEmpty(client, nameof(client)); @@ -101,11 +98,11 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase FindAsync(string subject, string client, string status, string type, ImmutableArray scopes, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindAsync(string subject, string client, string status, string type, ImmutableArray scopes, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); Check.NotNullOrEmpty(client, nameof(client)); @@ -116,43 +113,43 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase(await GetScopesAsync(authorization, cancellationToken), StringComparer.Ordinal).IsSupersetOf(scopes)) + if (new HashSet(await GetScopesAsync(authorization.ToModel(), cancellationToken), StringComparer.Ordinal).IsSupersetOf(scopes)) { - yield return authorization; + yield return authorization.ToModel(); } } } - public virtual async IAsyncEnumerable FindByApplicationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindByApplicationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); var authorizations = await Repository.FindByApplicationIdAsync(ConvertIdentifierFromString(identifier), cancellationToken); foreach (var authorization in authorizations) { - yield return authorization; + yield return authorization.ToModel(); } } - public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) + public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); - return await Repository.FindByIdAsync(ConvertIdentifierFromString(identifier), cancellationToken); + return (await Repository.FindByIdAsync(ConvertIdentifierFromString(identifier), cancellationToken)).ToModel(); } - public virtual async IAsyncEnumerable FindBySubjectAsync(string subject, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindBySubjectAsync(string subject, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); var authorizations = await Repository.FindBySubjectAsync(subject, cancellationToken); foreach (var authorization in authorizations) { - yield return authorization; + yield return authorization.ToModel(); } } - public virtual ValueTask GetApplicationIdAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual ValueTask GetApplicationIdAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); @@ -161,14 +158,12 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + public virtual ValueTask GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - return await Repository.GetAsync(query, state, cancellationToken); + throw new NotSupportedException(); } - public virtual ValueTask GetCreationDateAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual ValueTask GetCreationDateAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); @@ -177,14 +172,14 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase(DateTime.SpecifyKind(authorization.CreationDate.Value, DateTimeKind.Utc)); } - public virtual ValueTask GetIdAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual ValueTask GetIdAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); return new ValueTask(ConvertIdentifierToString(authorization.Id)); } - public virtual ValueTask > GetPropertiesAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual ValueTask > GetPropertiesAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); @@ -193,15 +188,8 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase>(ImmutableDictionary.Create()); } - // Note: parsing the stringified properties is an expensive operation. - // To mitigate that, the resulting object is stored in the memory cache. - var key = string.Concat("68056e1a-dbcf-412b-9a6a-d791c7dbe726", "\x1e", authorization.Properties); - var properties = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(authorization.Properties)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(authorization.Properties); var builder = ImmutableDictionary.CreateBuilder(); foreach (var property in document.RootElement.EnumerateObject()) @@ -209,13 +197,11 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase>(properties); + return new ValueTask>(builder.ToImmutable()); + } } - public virtual ValueTask > GetScopesAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual ValueTask > GetScopesAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); @@ -224,15 +210,8 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase>(ImmutableArray.Create()); } - // Note: parsing the stringified scopes is an expensive operation. - // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat("2ba4ab0f-e2ec-4d48-b3bd-28e2bb660c75", "\x1e", authorization.Scopes); - var scopes = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(authorization.Scopes)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(authorization.Scopes); var builder = ImmutableArray.CreateBuilder(document.RootElement.GetArrayLength()); foreach (var element in document.RootElement.EnumerateArray()) @@ -246,61 +225,51 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase>(scopes); + return new ValueTask>(builder.ToImmutable()); + } } - public virtual ValueTask GetStatusAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual ValueTask GetStatusAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); return new ValueTask(authorization.Status); } - public virtual ValueTask GetSubjectAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual ValueTask GetSubjectAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); return new ValueTask(authorization.Subject); } - public virtual ValueTask GetTypeAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) + public virtual ValueTask GetTypeAsync(OpenIddictAuthorizationModel authorization, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); return new ValueTask(authorization.Type); } - public virtual ValueTask InstantiateAsync(CancellationToken cancellationToken) + public virtual ValueTask InstantiateAsync(CancellationToken cancellationToken) { - try - { - return new ValueTask(Activator.CreateInstance()); - } - catch (MemberAccessException exception) + return new ValueTask(new OpenIddictAuthorizationModel { - return new ValueTask(Task.FromException(exception)); - } + Id = GuidGenerator.Create() + }); } - public virtual async IAsyncEnumerable ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) { var authorizations = await Repository.ListAsync(count, offset, cancellationToken); foreach (var authorization in authorizations) { - yield return authorization; + yield return authorization.ToModel(); } } - public virtual async IAsyncEnumerable ListAsync(Func, TState, IQueryable> query, TState state, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual IAsyncEnumerable ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - var authorizations = await Repository.ListAsync(query, state, cancellationToken); - foreach (var authorization in authorizations) - { - yield return authorization; - } + throw new NotSupportedException(); } public virtual async ValueTask PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken) @@ -325,7 +294,7 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase properties, CancellationToken cancellationToken) + public virtual ValueTask SetPropertiesAsync(OpenIddictAuthorizationModel authorization, ImmutableDictionary properties, CancellationToken cancellationToken) { if (properties is null || properties.IsEmpty) { @@ -371,7 +340,7 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase scopes, CancellationToken cancellationToken) + public virtual ValueTask SetScopesAsync(OpenIddictAuthorizationModel authorization, ImmutableArray scopes, CancellationToken cancellationToken) { Check.NotNull(authorization, nameof(authorization)); @@ -394,7 +363,7 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase { - Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default); - Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default); Task> FindAsync(string subject, Guid client, string status, CancellationToken cancellationToken = default); @@ -23,11 +20,7 @@ public interface IOpenIddictAuthorizationRepository : IBasicRepository> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default); - Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default); - Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorization.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorization.cs index 7dbb31aace..4f6de478e4 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorization.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorization.cs @@ -5,6 +5,15 @@ namespace Volo.Abp.OpenIddict.Authorizations; public class OpenIddictAuthorization : FullAuditedAggregateRoot { + public OpenIddictAuthorization() + { + } + + public OpenIddictAuthorization(Guid id) + : base(id) + { + } + /// /// Gets or sets the application associated with the current authorization. /// diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationExtensions.cs new file mode 100644 index 0000000000..3d260375df --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationExtensions.cs @@ -0,0 +1,56 @@ +namespace Volo.Abp.OpenIddict.Authorizations; + +public static class OpenIddictAuthorizationExtensions +{ + public static OpenIddictAuthorization ToEntity(this OpenIddictAuthorizationModel model) + { + Check.NotNull(model, nameof(model)); + + return new OpenIddictAuthorization(model.Id) + { + ApplicationId = model.ApplicationId, + CreationDate = model.CreationDate, + Properties = model.Properties, + Scopes = model.Scopes, + Status = model.Status, + Subject = model.Subject, + Type = model.Type + }; + } + + public static OpenIddictAuthorization ToEntity(this OpenIddictAuthorizationModel model, OpenIddictAuthorization entity) + { + Check.NotNull(model, nameof(model)); + Check.NotNull(entity, nameof(entity)); + + entity.ApplicationId = model.ApplicationId; + entity.CreationDate = model.CreationDate; + entity.Properties = model.Properties; + entity.Scopes = model.Scopes; + entity.Status = model.Status; + entity.Subject = model.Subject; + entity.Type = model.Type; + + return entity; + } + + public static OpenIddictAuthorizationModel ToModel(this OpenIddictAuthorization model) + { + if(model == null) + { + return null; + } + + return new OpenIddictAuthorizationModel + { + Id = model.Id, + ApplicationId = model.ApplicationId, + CreationDate = model.CreationDate, + Properties = model.Properties, + Scopes = model.Scopes, + Status = model.Status, + Subject = model.Subject, + Type = model.Type + }; + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationModel.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationModel.cs new file mode 100644 index 0000000000..7b427aca6b --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationModel.cs @@ -0,0 +1,47 @@ +using System; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.OpenIddict.Authorizations; + +[Serializable, IgnoreMultiTenancy] +public class OpenIddictAuthorizationModel +{ + public Guid Id { get; set; } + + /// + /// Gets or sets the application associated with the current authorization. + /// + public virtual Guid? ApplicationId { get; set; } + + /// + /// Gets or sets the UTC creation date of the current authorization. + /// + public virtual DateTime? CreationDate { get; set; } + + /// + /// Gets or sets the additional properties serialized as a JSON object, + /// or null if no bag was associated with the current authorization. + /// + public virtual string Properties { get; set; } + + /// + /// Gets or sets the scopes associated with the current + /// authorization, serialized as a JSON array. + /// + public virtual string Scopes { get; set; } + + /// + /// Gets or sets the status of the current authorization. + /// + public virtual string Status { get; set; } + + /// + /// Gets or sets the subject associated with the current authorization. + /// + public virtual string Subject { get; set; } + + /// + /// Gets or sets the type of the current authorization. + /// + public virtual string Type { get; set; } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeCache.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeCache.cs new file mode 100644 index 0000000000..521e11f5c8 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeCache.cs @@ -0,0 +1,111 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using OpenIddict.Abstractions; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.OpenIddict.Scopes; + +public class AbpOpenIddictScopeCacheAbpOpenIddictAuthorizationCache : AbpOpenIddictCacheBase>, + IOpenIddictScopeCache, + ITransientDependency +{ + public AbpOpenIddictScopeCacheAbpOpenIddictAuthorizationCache( + IDistributedCache cache, + IDistributedCache arrayCache, + IOpenIddictScopeStore store) + : base(cache, arrayCache, store) + { + } + + public virtual async ValueTask AddAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) + { + Check.NotNull(scope, nameof(scope)); + + await RemoveAsync(scope, cancellationToken); + + await Cache.SetAsync($"{nameof(FindByIdAsync)}_{await Store.GetIdAsync(scope, cancellationToken)}", scope, token: cancellationToken); + await Cache.SetAsync($"{nameof(FindByNameAsync)}_{await Store.GetNameAsync(scope, cancellationToken)}", scope, token: cancellationToken); + } + + public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + return await Cache.GetOrAddAsync($"{nameof(FindByIdAsync)}_{identifier}", async () => + { + var scope = await Store.FindByIdAsync(identifier, cancellationToken); + if (scope != null) + { + await AddAsync(scope, cancellationToken); + } + return scope; + }, token: cancellationToken); + } + + public virtual async ValueTask FindByNameAsync(string name, CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(name, nameof(name)); + + return await Cache.GetOrAddAsync($"{nameof(FindByNameAsync)}_{name}", async () => + { + var scope = await Store.FindByNameAsync(name, cancellationToken); + if (scope != null) + { + await AddAsync(scope, cancellationToken); + } + return scope; + }, token: cancellationToken); + } + + public virtual async IAsyncEnumerable FindByNamesAsync(ImmutableArray names, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(names, nameof(names)); + + // Note: this method is only partially cached. + await foreach (var scope in Store.FindByNamesAsync(names, cancellationToken)) + { + await AddAsync(scope, cancellationToken); + yield return scope; + } + } + + public virtual async IAsyncEnumerable FindByResourceAsync(string resource, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(resource, nameof(resource)); + + var scopes = await ArrayCache.GetOrAddAsync($"{nameof(FindByResourceAsync)}_{resource}", async () => + { + var scopes = new List(); + await foreach (var scope in Store.FindByResourceAsync(resource, cancellationToken)) + { + scopes.Add(scope); + await AddAsync(scope, cancellationToken); + } + return scopes.ToArray(); + }, token: cancellationToken); + + foreach (var scope in scopes) + { + yield return scope; + } + } + + public virtual async ValueTask RemoveAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) + { + Check.NotNull(scope, nameof(scope)); + + var resources = new List(); + foreach (var resource in await Store.GetResourcesAsync(scope, cancellationToken)) + { + resources.Add($"{nameof(FindByResourceAsync)}_{resource}"); + } + await ArrayCache.RemoveManyAsync(resources.ToArray(), token: cancellationToken); + + await Cache.RemoveAsync($"{nameof(FindByIdAsync)}_{await Store.GetIdAsync(scope, cancellationToken)}", token: cancellationToken); + await Cache.RemoveAsync($"{nameof(FindByNameAsync)}_{await Store.GetNameAsync(scope, cancellationToken)}", token: cancellationToken); + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore.cs index c538c21170..d60baf0e1c 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore.cs @@ -7,20 +7,19 @@ using System.Runtime.CompilerServices; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; using OpenIddict.Abstractions; -using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict.Scopes; -public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase, IOpenIddictScopeStore, IScopedDependency +public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase, IOpenIddictScopeStore { - public AbpOpenIddictScopeStore( + public AbpOpenIddictScopeStore( IOpenIddictScopeRepository repository, IUnitOfWorkManager unitOfWorkManager, - IMemoryCache cache) - : base(repository, unitOfWorkManager, cache) + IGuidGenerator guidGenerator) + : base(repository, unitOfWorkManager, guidGenerator) { } @@ -30,42 +29,40 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) + public virtual ValueTask CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - return await Repository.CountAsync(query, cancellationToken); + throw new NotSupportedException(); } - public virtual async ValueTask CreateAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual async ValueTask CreateAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); - await Repository.InsertAsync(scope, autoSave: true, cancellationToken: cancellationToken); + await Repository.InsertAsync(scope.ToEntity(), autoSave: true, cancellationToken: cancellationToken); } - public virtual async ValueTask DeleteAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual async ValueTask DeleteAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); - await Repository.DeleteAsync(scope, autoSave: true, cancellationToken: cancellationToken); + await Repository.DeleteAsync(scope.Id, autoSave: true, cancellationToken: cancellationToken); } - public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) + public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); - return await Repository.FindByIdAsync(ConvertIdentifierFromString(identifier), cancellationToken); + return (await Repository.FindByIdAsync(ConvertIdentifierFromString(identifier), cancellationToken)).ToModel(); } - public virtual async ValueTask FindByNameAsync(string name, CancellationToken cancellationToken) + public virtual async ValueTask FindByNameAsync(string name, CancellationToken cancellationToken) { Check.NotNullOrEmpty(name, nameof(name)); - return await Repository.FindByNameAsync(name, cancellationToken); + return (await Repository.FindByNameAsync(name, cancellationToken)).ToModel(); } - public virtual async IAsyncEnumerable FindByNamesAsync(ImmutableArray names, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindByNamesAsync(ImmutableArray names, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(names, nameof(names)); foreach (var name in names) @@ -76,38 +73,38 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase FindByResourceAsync(string resource, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindByResourceAsync(string resource, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(resource, nameof(resource)); var scopes = await Repository.FindByResourceAsync(resource, cancellationToken); foreach (var scope in scopes) { - var resources = await GetResourcesAsync(scope, cancellationToken); + var resources = await GetResourcesAsync(scope.ToModel(), cancellationToken); if (resources.Contains(resource, StringComparer.Ordinal)) { - yield return scope; + yield return scope.ToModel(); } } } - public virtual async ValueTask GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + public virtual ValueTask GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - return await Repository.GetAsync(query, state, cancellationToken); + throw new NotSupportedException(); } - public virtual ValueTask GetDescriptionAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual ValueTask GetDescriptionAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); return new ValueTask(scope.Description); } - public virtual ValueTask> GetDescriptionsAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual ValueTask> GetDescriptionsAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -116,15 +113,8 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase>(ImmutableDictionary.Create()); } - // Note: parsing the stringified descriptions is an expensive operation. - // To mitigate that, the resulting object is stored in the memory cache. - var key = string.Concat("42891062-8f69-43ba-9111-db7e8ded2553", "\x1e", scope.Descriptions); - var descriptions = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(scope.Descriptions)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(scope.Descriptions); var builder = ImmutableDictionary.CreateBuilder(); foreach (var property in document.RootElement.EnumerateObject()) @@ -138,20 +128,18 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase>(descriptions); + return new ValueTask>(builder.ToImmutable()); + } } - public virtual ValueTask GetDisplayNameAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual ValueTask GetDisplayNameAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); return new ValueTask(scope.DisplayName); } - public virtual ValueTask> GetDisplayNamesAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual ValueTask> GetDisplayNamesAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -160,15 +148,8 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase>(ImmutableDictionary.Create()); } - // Note: parsing the stringified display names is an expensive operation. - // To mitigate that, the resulting object is stored in the memory cache. - var key = string.Concat("e17d437b-bdd2-43f3-974e-46d524f4bae1", "\x1e", scope.DisplayNames); - var names = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(scope.DisplayNames)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(scope.DisplayNames); var builder = ImmutableDictionary.CreateBuilder(); foreach (var property in document.RootElement.EnumerateObject()) @@ -182,27 +163,25 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase>(names); + return new ValueTask>(builder.ToImmutable()); + } } - public virtual ValueTask GetIdAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual ValueTask GetIdAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); return new ValueTask(ConvertIdentifierToString(scope.Id)); } - public virtual ValueTask GetNameAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual ValueTask GetNameAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); return new ValueTask(scope.Name); } - public virtual ValueTask> GetPropertiesAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual ValueTask> GetPropertiesAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -211,15 +190,8 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase>(ImmutableDictionary.Create()); } - // Note: parsing the stringified properties is an expensive operation. - // To mitigate that, the resulting object is stored in the memory cache. - var key = string.Concat("78d8dfdd-3870-442e-b62e-dc9bf6eaeff7", "\x1e", scope.Properties); - var properties = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(scope.Properties)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(scope.Properties); var builder = ImmutableDictionary.CreateBuilder(); foreach (var property in document.RootElement.EnumerateObject()) @@ -227,13 +199,11 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase>(properties); + return new ValueTask>(builder.ToImmutable()); + } } - public virtual ValueTask> GetResourcesAsync(OpenIddictScope scope, CancellationToken cancellationToken) + public virtual ValueTask> GetResourcesAsync(OpenIddictScopeModel scope, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -242,15 +212,8 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase>(ImmutableArray.Create()); } - // Note: parsing the stringified resources is an expensive operation. - // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat("b6148250-aede-4fb9-a621-07c9bcf238c3", "\x1e", scope.Resources); - var resources = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(scope.Resources)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(scope.Resources); var builder = ImmutableArray.CreateBuilder(document.RootElement.GetArrayLength()); foreach (var element in document.RootElement.EnumerateArray()) @@ -264,45 +227,33 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase>(resources); + return new ValueTask>(builder.ToImmutable()); + } } - public virtual ValueTask InstantiateAsync(CancellationToken cancellationToken) + public virtual ValueTask InstantiateAsync(CancellationToken cancellationToken) { - try + return new ValueTask(new OpenIddictScopeModel { - return new ValueTask(Activator.CreateInstance()); - } - catch (MemberAccessException exception) - { - return new ValueTask(Task.FromException(exception)); - } + Id = GuidGenerator.Create() + }); } - public virtual async IAsyncEnumerable ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) { var scopes = await Repository.ListAsync(count, offset, cancellationToken); foreach (var scope in scopes) { - yield return scope; + yield return scope.ToModel(); } } - public async IAsyncEnumerable ListAsync(Func, TState, IQueryable> query, TState state, [EnumeratorCancellation] CancellationToken cancellationToken) + public IAsyncEnumerable ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - var scopes = await Repository.ListAsync(query, state, cancellationToken); - foreach (var scope in scopes) - { - yield return scope; - } + throw new NotSupportedException(); } - public virtual ValueTask SetDescriptionAsync(OpenIddictScope scope, string description, CancellationToken cancellationToken) + public virtual ValueTask SetDescriptionAsync(OpenIddictScopeModel scope, string description, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -311,7 +262,7 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase descriptions, CancellationToken cancellationToken) + public virtual ValueTask SetDescriptionsAsync(OpenIddictScopeModel scope, ImmutableDictionary descriptions, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -335,7 +286,7 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase names, CancellationToken cancellationToken) + public virtual ValueTask SetDisplayNamesAsync(OpenIddictScopeModel scope, ImmutableDictionary names, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -368,7 +319,7 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase properties, CancellationToken cancellationToken) + public virtual ValueTask SetPropertiesAsync(OpenIddictScopeModel scope, ImmutableDictionary properties, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -401,7 +352,7 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase resources, CancellationToken cancellationToken) + public virtual ValueTask SetResourcesAsync(OpenIddictScopeModel scope, ImmutableArray resources, CancellationToken cancellationToken) { Check.NotNull(scope, nameof(scope)); @@ -424,10 +375,12 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase { - Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default); - Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default); Task FindByNameAsync(string name, CancellationToken cancellationToken = default); @@ -19,9 +16,5 @@ public interface IOpenIddictScopeRepository : IBasicRepository> FindByResourceAsync(string resource, CancellationToken cancellationToken = default); - Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default); - - Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScope.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScope.cs index b8114cebf9..bc04ac57c6 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScope.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScope.cs @@ -5,6 +5,15 @@ namespace Volo.Abp.OpenIddict.Scopes; public class OpenIddictScope : FullAuditedAggregateRoot { + public OpenIddictScope() + { + } + + public OpenIddictScope(Guid id) + : base(id) + { + } + /// /// Gets or sets the public description associated with the current scope. /// diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeExtensions.cs new file mode 100644 index 0000000000..d9f858abc1 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeExtensions.cs @@ -0,0 +1,56 @@ +namespace Volo.Abp.OpenIddict.Scopes; + +public static class OpenIddictScopeExtensions +{ + public static OpenIddictScope ToEntity(this OpenIddictScopeModel model) + { + Check.NotNull(model, nameof(model)); + + return new OpenIddictScope(model.Id) + { + Description = model.Description, + Descriptions = model.Descriptions, + DisplayName = model.DisplayName, + DisplayNames = model.DisplayNames, + Name = model.Name, + Properties = model.Properties, + Resources = model.Resources + }; + } + + public static OpenIddictScope ToEntity(this OpenIddictScopeModel model, OpenIddictScope entity) + { + Check.NotNull(model, nameof(model)); + Check.NotNull(entity, nameof(entity)); + + entity.Description = model.Description; + entity.Descriptions = model.Descriptions; + entity.DisplayName = model.DisplayName; + entity.DisplayNames = model.DisplayNames; + entity.Name = model.Name; + entity.Properties = model.Properties; + entity.Resources = model.Resources; + + return entity; + } + + public static OpenIddictScopeModel ToModel(this OpenIddictScope model) + { + if(model == null) + { + return null; + } + + return new OpenIddictScopeModel + { + Id = model.Id, + Description = model.Description, + Descriptions = model.Descriptions, + DisplayName = model.DisplayName, + DisplayNames = model.DisplayNames, + Name = model.Name, + Properties = model.Properties, + Resources = model.Resources + }; + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeModel.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeModel.cs new file mode 100644 index 0000000000..807ae3fff9 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeModel.cs @@ -0,0 +1,50 @@ +using System; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.OpenIddict.Scopes; + +[Serializable, IgnoreMultiTenancy] +public class OpenIddictScopeModel +{ + public Guid Id { get; set; } + + /// + /// Gets or sets the public description associated with the current scope. + /// + public virtual string Description { get; set; } + + /// + /// Gets or sets the localized public descriptions associated + /// with the current scope, serialized as a JSON object. + /// + public virtual string Descriptions { get; set; } + + /// + /// Gets or sets the display name associated with the current scope. + /// + public virtual string DisplayName { get; set; } + + /// + /// Gets or sets the localized display names + /// associated with the current application, + /// serialized as a JSON object. + /// + public virtual string DisplayNames { get; set; } + + /// + /// Gets or sets the unique name associated with the current scope. + /// + public virtual string Name { get; set; } + + /// + /// Gets or sets the additional properties serialized as a JSON object, + /// or null if no bag was associated with the current scope. + /// + public virtual string Properties { get; set; } + + /// + /// Gets or sets the resources associated with the + /// current scope, serialized as a JSON array. + /// + public virtual string Resources { get; set; } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenCache.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenCache.cs new file mode 100644 index 0000000000..1ec1743ae6 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenCache.cs @@ -0,0 +1,210 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using OpenIddict.Abstractions; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.OpenIddict.Tokens; + +public class AbpOpenIddictTokenCache : AbpOpenIddictCacheBase>, + IOpenIddictTokenCache, + ITransientDependency +{ + public AbpOpenIddictTokenCache( + IDistributedCache cache, + IDistributedCache arrayCache, + IOpenIddictTokenStore store) + : base(cache, arrayCache, store) + { + } + + public virtual async ValueTask AddAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) + { + Check.NotNull(token, nameof(token)); + + await RemoveAsync(token, cancellationToken); + + await Cache.SetAsync($"{nameof(FindByIdAsync)}_{await Store.GetIdAsync(token, cancellationToken)}", token, token: cancellationToken); + await Cache.SetAsync($"{nameof(FindByReferenceIdAsync)}_{await Store.GetReferenceIdAsync(token, cancellationToken)}", token, token: cancellationToken); + } + + public virtual async IAsyncEnumerable FindAsync(string subject, string client, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + Check.NotNullOrEmpty(client, nameof(client)); + + var tokens = await ArrayCache.GetOrAddAsync($"{nameof(FindAsync)}_{subject}_{client}", async () => + { + var tokens = new List(); + await foreach (var token in Store.FindAsync(subject, client, cancellationToken)) + { + tokens.Add(token); + await AddAsync(token, cancellationToken); + } + return tokens.ToArray(); + }, token: cancellationToken); + + foreach (var token in tokens) + { + yield return token; + } + } + + public virtual async IAsyncEnumerable FindAsync(string subject, string client, string status, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + Check.NotNullOrEmpty(client, nameof(client)); + Check.NotNullOrEmpty(status, nameof(status)); + + var tokens = await ArrayCache.GetOrAddAsync($"{nameof(FindAsync)}_{subject}_{client}_{status}", async () => + { + var tokens = new List(); + await foreach (var token in Store.FindAsync(subject, client, status, cancellationToken)) + { + tokens.Add(token); + await AddAsync(token, cancellationToken); + } + return tokens.ToArray(); + }, token: cancellationToken); + + foreach (var token in tokens) + { + yield return token; + } + } + + public virtual async IAsyncEnumerable FindAsync(string subject, string client, string status, string type, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + Check.NotNullOrEmpty(client, nameof(client)); + Check.NotNullOrEmpty(status, nameof(status)); + Check.NotNullOrEmpty(type, nameof(type)); + + var tokens = await ArrayCache.GetOrAddAsync($"{nameof(FindAsync)}_{subject}_{client}_{status}_{type}", async () => + { + var tokens = new List(); + await foreach (var token in Store.FindAsync(subject, client, status, type, cancellationToken)) + { + tokens.Add(token); + await AddAsync(token, cancellationToken); + } + return tokens.ToArray(); + }, token: cancellationToken); + + foreach (var token in tokens) + { + yield return token; + } + } + + public virtual async IAsyncEnumerable FindByApplicationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + var tokens = await ArrayCache.GetOrAddAsync($"{nameof(FindByApplicationIdAsync)}_{identifier}", async () => + { + var tokens = new List(); + await foreach (var token in Store.FindByApplicationIdAsync(identifier, cancellationToken)) + { + tokens.Add(token); + await AddAsync(token, cancellationToken); + } + return tokens.ToArray(); + }, token: cancellationToken); + + foreach (var token in tokens) + { + yield return token; + } + } + + public virtual async IAsyncEnumerable FindByAuthorizationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + var tokens = await ArrayCache.GetOrAddAsync($"{nameof(FindByAuthorizationIdAsync)}_{identifier}", async () => + { + var tokens = new List(); + await foreach (var token in Store.FindByAuthorizationIdAsync(identifier, cancellationToken)) + { + tokens.Add(token); + await AddAsync(token, cancellationToken); + } + return tokens.ToArray(); + }, token: cancellationToken); + + foreach (var token in tokens) + { + yield return token; + } + } + + public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + return await Cache.GetOrAddAsync($"{nameof(FindByIdAsync)}_{identifier}", async () => + { + var token = await Store.FindByIdAsync(identifier, cancellationToken); + if (token != null) + { + await AddAsync(token, cancellationToken); + } + return token; + }, token: cancellationToken); + } + + public virtual async ValueTask FindByReferenceIdAsync(string identifier, CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(identifier, nameof(identifier)); + + return await Cache.GetOrAddAsync($"{nameof(FindByReferenceIdAsync)}_{identifier}", async () => + { + var token = await Store.FindByReferenceIdAsync(identifier, cancellationToken); + if (token != null) + { + await AddAsync(token, cancellationToken); + } + return token; + }, token: cancellationToken); + } + + public virtual async IAsyncEnumerable FindBySubjectAsync(string subject, [EnumeratorCancellation] CancellationToken cancellationToken) + { + Check.NotNullOrEmpty(subject, nameof(subject)); + + var tokens = await ArrayCache.GetOrAddAsync($"{nameof(FindBySubjectAsync)}_{subject}", async () => + { + var tokens = new List(); + await foreach (var token in Store.FindBySubjectAsync(subject, cancellationToken)) + { + tokens.Add(token); + await AddAsync(token, cancellationToken); + } + return tokens.ToArray(); + }, token: cancellationToken); + + foreach (var token in tokens) + { + yield return token; + } + } + + public virtual async ValueTask RemoveAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) + { + await ArrayCache.RemoveManyAsync(new[] + { + $"{nameof(FindAsync)}_{await Store.GetSubjectAsync(token, cancellationToken)}_{await Store.GetApplicationIdAsync(token, cancellationToken)}", + $"{nameof(FindAsync)}_{await Store.GetSubjectAsync(token, cancellationToken)}_{await Store.GetApplicationIdAsync(token, cancellationToken)}_{Store.GetStatusAsync(token, cancellationToken)}", + $"{nameof(FindAsync)}_{await Store.GetSubjectAsync(token, cancellationToken)}_{await Store.GetApplicationIdAsync(token, cancellationToken)}_{Store.GetStatusAsync(token, cancellationToken)}_{Store.GetTypeAsync(token, cancellationToken)}", + $"{nameof(FindByApplicationIdAsync)}_{await Store.GetApplicationIdAsync(token, cancellationToken)}", + $"{nameof(FindByAuthorizationIdAsync)}_{await Store.GetAuthorizationIdAsync(token, cancellationToken)}", + $"{nameof(FindBySubjectAsync)}_{await Store.GetSubjectAsync(token, cancellationToken)}" + }, token: cancellationToken); + + await Cache.RemoveAsync($"{nameof(FindByIdAsync)}_{await Store.GetIdAsync(token, cancellationToken)}", token: cancellationToken); + await Cache.RemoveAsync($"{nameof(FindByReferenceIdAsync)}_{await Store.GetReferenceIdAsync(token, cancellationToken)}", token: cancellationToken); + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore.cs index 3a22e727f5..e991acce6b 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore.cs @@ -7,16 +7,15 @@ using System.Runtime.CompilerServices; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; using OpenIddict.Abstractions; -using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; using Volo.Abp.OpenIddict.Applications; using Volo.Abp.OpenIddict.Authorizations; using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict.Tokens; -public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase, IOpenIddictTokenStore, IScopedDependency +public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase, IOpenIddictTokenStore { protected IOpenIddictApplicationRepository ApplicationRepository { get; } protected IOpenIddictAuthorizationRepository AuthorizationRepository { get; } @@ -24,10 +23,10 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) + public virtual ValueTask CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) { - return await Repository.CountAsync(query, cancellationToken); + throw new NotSupportedException(); } - public virtual async ValueTask CreateAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual async ValueTask CreateAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); - await Repository.InsertAsync(token, autoSave: true, cancellationToken: cancellationToken); + await Repository.InsertAsync(token.ToEntity(), autoSave: true, cancellationToken: cancellationToken); } - public virtual async ValueTask DeleteAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual async ValueTask DeleteAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); - await Repository.DeleteAsync(token, autoSave: true, cancellationToken: cancellationToken); + await Repository.DeleteAsync(token.ToEntity(), autoSave: true, cancellationToken: cancellationToken); } - public virtual async IAsyncEnumerable FindAsync(string subject, string client, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindAsync(string subject, string client, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); Check.NotNullOrEmpty(client, nameof(client)); @@ -65,11 +64,11 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase FindAsync(string subject, string client, string status, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindAsync(string subject, string client, string status, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); Check.NotNullOrEmpty(client, nameof(client)); @@ -78,11 +77,11 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase FindAsync(string subject, string client, string status, string type, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindAsync(string subject, string client, string status, string type, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); Check.NotNullOrEmpty(client, nameof(client)); @@ -92,58 +91,58 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase FindByApplicationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindByApplicationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); var tokens = await Repository.FindByApplicationIdAsync(ConvertIdentifierFromString(identifier), cancellationToken); foreach (var token in tokens) { - yield return token; + yield return token.ToModel(); } } - public virtual async IAsyncEnumerable FindByAuthorizationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindByAuthorizationIdAsync(string identifier, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); var tokens = await Repository.FindByAuthorizationIdAsync(ConvertIdentifierFromString(identifier), cancellationToken); foreach (var token in tokens) { - yield return token; + yield return token.ToModel(); } } - public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) + public virtual async ValueTask FindByIdAsync(string identifier, CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); - return await Repository.FindByIdAsync(ConvertIdentifierFromString(identifier), cancellationToken); + return (await Repository.FindByIdAsync(ConvertIdentifierFromString(identifier), cancellationToken)).ToModel(); } - public virtual async ValueTask FindByReferenceIdAsync(string identifier, CancellationToken cancellationToken) + public virtual async ValueTask FindByReferenceIdAsync(string identifier, CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); - return await Repository.FindByReferenceIdAsync(identifier, cancellationToken); + return (await Repository.FindByReferenceIdAsync(identifier, cancellationToken)).ToModel(); } - public virtual async IAsyncEnumerable FindBySubjectAsync(string subject, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable FindBySubjectAsync(string subject, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); var tokens = await Repository.FindBySubjectAsync(subject, cancellationToken); foreach (var token in tokens) { - yield return token; + yield return token.ToModel(); } } - public virtual ValueTask GetApplicationIdAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetApplicationIdAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); @@ -152,14 +151,12 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + public virtual ValueTask GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - return await Repository.GetAsync(query, state, cancellationToken); + throw new NotSupportedException(); } - public virtual ValueTask GetAuthorizationIdAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetAuthorizationIdAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); @@ -168,7 +165,7 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase GetCreationDateAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetCreationDateAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); @@ -180,7 +177,7 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase(DateTime.SpecifyKind(token.CreationDate.Value, DateTimeKind.Utc)); } - public virtual ValueTask GetExpirationDateAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetExpirationDateAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); @@ -192,21 +189,21 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase(DateTime.SpecifyKind(token.ExpirationDate.Value, DateTimeKind.Utc)); } - public virtual ValueTask GetIdAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetIdAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); return new ValueTask(ConvertIdentifierToString(token.Id)); } - public virtual ValueTask GetPayloadAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetPayloadAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); return new ValueTask(token.Payload); } - public virtual ValueTask> GetPropertiesAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask> GetPropertiesAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); @@ -215,15 +212,8 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase>(ImmutableDictionary.Create()); } - // Note: parsing the stringified properties is an expensive operation. - // To mitigate that, the resulting object is stored in the memory cache. - var key = string.Concat("d0509397-1bbf-40e7-97e1-5e6d7bc2536c", "\x1e", token.Properties); - var properties = Cache.GetOrCreate(key, entry => + using (var document = JsonDocument.Parse(token.Properties)) { - entry.SetPriority(CacheItemPriority.High) - .SetSlidingExpiration(TimeSpan.FromMinutes(1)); - - using var document = JsonDocument.Parse(token.Properties); var builder = ImmutableDictionary.CreateBuilder(); foreach (var property in document.RootElement.EnumerateObject()) @@ -231,13 +221,11 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase>(properties); + return new ValueTask>(builder.ToImmutable()); + } } - public virtual ValueTask GetRedemptionDateAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetRedemptionDateAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); @@ -249,64 +237,54 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase(DateTime.SpecifyKind(token.RedemptionDate.Value, DateTimeKind.Utc)); } - public virtual ValueTask GetReferenceIdAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetReferenceIdAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); return new ValueTask(token.ReferenceId); } - public virtual ValueTask GetStatusAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetStatusAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); return new ValueTask(token.Status); } - public virtual ValueTask GetSubjectAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetSubjectAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); return new ValueTask(token.Subject); } - public virtual ValueTask GetTypeAsync(OpenIddictToken token, CancellationToken cancellationToken) + public virtual ValueTask GetTypeAsync(OpenIddictTokenModel token, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); return new ValueTask(token.Type); } - public virtual ValueTask InstantiateAsync(CancellationToken cancellationToken) + public virtual ValueTask InstantiateAsync(CancellationToken cancellationToken) { - try - { - return new ValueTask(Activator.CreateInstance()); - } - catch (MemberAccessException exception) + return new ValueTask(new OpenIddictTokenModel { - return new ValueTask(Task.FromException(exception)); - } + Id = GuidGenerator.Create() + }); } - public virtual async IAsyncEnumerable ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual async IAsyncEnumerable ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) { var tokens = await Repository.ListAsync(count, offset, cancellationToken); foreach (var token in tokens) { - yield return token; + yield return token.ToModel(); } } - public virtual async IAsyncEnumerable ListAsync(Func, TState, IQueryable> query, TState state, [EnumeratorCancellation] CancellationToken cancellationToken) + public virtual IAsyncEnumerable ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - Check.NotNull(query, nameof(query)); - - var tokens = await Repository.ListAsync(query, state, cancellationToken); - foreach (var token in tokens) - { - yield return token; - } + throw new NotSupportedException(); } public virtual async ValueTask PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken) @@ -331,7 +309,7 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase properties, CancellationToken cancellationToken) + public virtual ValueTask SetPropertiesAsync(OpenIddictTokenModel token, ImmutableDictionary properties, CancellationToken cancellationToken) { Check.NotNull(token, nameof(token)); @@ -412,7 +390,7 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default); - Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default); Task> FindAsync(string subject, Guid client, string status, CancellationToken cancellationToken = default); @@ -31,11 +28,7 @@ public interface IOpenIddictTokenRepository : IBasicRepository> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default); - Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default); - Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictToken.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictToken.cs index eb49651e2f..3cbccedcab 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictToken.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictToken.cs @@ -5,6 +5,15 @@ namespace Volo.Abp.OpenIddict.Tokens; public class OpenIddictToken : FullAuditedAggregateRoot { + public OpenIddictToken() + { + } + + public OpenIddictToken(Guid id) + : base(id) + { + } + /// /// Gets or sets the application associated with the current token. /// diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenExtensions.cs new file mode 100644 index 0000000000..0aab8c6b65 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenExtensions.cs @@ -0,0 +1,68 @@ +namespace Volo.Abp.OpenIddict.Tokens; + +public static class OpenIddictTokenExtensions +{ + public static OpenIddictToken ToEntity(this OpenIddictTokenModel model) + { + Check.NotNull(model, nameof(model)); + + return new OpenIddictToken(model.Id) + { + ApplicationId = model.ApplicationId, + AuthorizationId = model.AuthorizationId, + CreationDate = model.CreationDate, + ExpirationDate = model.ExpirationDate, + Payload = model.Payload, + Properties = model.Properties, + RedemptionDate = model.RedemptionDate, + ReferenceId = model.ReferenceId, + Status = model.Status, + Subject = model.Subject, + Type = model.Type + }; + } + + public static OpenIddictToken ToEntity(this OpenIddictTokenModel model, OpenIddictToken entity) + { + Check.NotNull(model, nameof(model)); + Check.NotNull(entity, nameof(entity)); + + entity.ApplicationId = model.ApplicationId; + entity.AuthorizationId = model.AuthorizationId; + entity.CreationDate = model.CreationDate; + entity.ExpirationDate = model.ExpirationDate; + entity.Payload = model.Payload; + entity.Properties = model.Properties; + entity.RedemptionDate = model.RedemptionDate; + entity.ReferenceId = model.ReferenceId; + entity.Status = model.Status; + entity.Subject = model.Subject; + entity.Type = model.Type; + + return entity; + } + + public static OpenIddictTokenModel ToModel(this OpenIddictToken model) + { + if(model == null) + { + return null; + } + + return new OpenIddictTokenModel + { + Id = model.Id, + ApplicationId = model.ApplicationId, + AuthorizationId = model.AuthorizationId, + CreationDate = model.CreationDate, + ExpirationDate = model.ExpirationDate, + Payload = model.Payload, + Properties = model.Properties, + RedemptionDate = model.RedemptionDate, + ReferenceId = model.ReferenceId, + Status = model.Status, + Subject = model.Subject, + Type = model.Type + }; + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenModel.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenModel.cs new file mode 100644 index 0000000000..7f891e0ec6 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenModel.cs @@ -0,0 +1,71 @@ +using System; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.OpenIddict.Tokens; + +[Serializable, IgnoreMultiTenancy] +public class OpenIddictTokenModel +{ + public Guid Id { get; set; } + + /// + /// Gets or sets the application associated with the current token. + /// + public virtual Guid? ApplicationId { get; set; } + + /// + /// Gets or sets the authorization associated with the current token. + /// + public virtual Guid? AuthorizationId { get; set; } + + /// + /// Gets or sets the UTC creation date of the current token. + /// + public virtual DateTime? CreationDate { get; set; } + + /// + /// Gets or sets the UTC expiration date of the current token. + /// + public virtual DateTime? ExpirationDate { get; set; } + + /// + /// Gets or sets the payload of the current token, if applicable. + /// Note: this property is only used for reference tokens + /// and may be encrypted for security reasons. + /// + public virtual string Payload { get; set; } + + /// + /// Gets or sets the additional properties serialized as a JSON object, + /// or null if no bag was associated with the current token. + /// + public virtual string Properties { get; set; } + + /// + /// Gets or sets the UTC redemption date of the current token. + /// + public virtual DateTime? RedemptionDate { get; set; } + + /// + /// Gets or sets the reference identifier associated + /// with the current token, if applicable. + /// Note: this property is only used for reference tokens + /// and may be hashed or encrypted for security reasons. + /// + public virtual string ReferenceId { get; set; } + + /// + /// Gets or sets the status of the current token. + /// + public virtual string Status { get; set; } + + /// + /// Gets or sets the subject associated with the current token. + /// + public virtual string Subject { get; set; } + + /// + /// Gets or sets the type of the current token. + /// + public virtual string Type { get; set; } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs index c4300d3fff..8daa0094bb 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs @@ -18,35 +18,24 @@ public class EfCoreOpenIddictApplicationRepository : EfCoreRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await query(await GetDbSetAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task FindByClientIdAsync(string clientId, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) .FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken = default) + public virtual async Task> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) .Where(x => x.PostLogoutRedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByRedirectUriAsync(string address, CancellationToken cancellationToken = default) + public virtual async Task> FindByRedirectUriAsync(string address, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) .Where(x => x.RedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetDbSetAsync(), state) - .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) @@ -55,10 +44,4 @@ public class EfCoreOpenIddictApplicationRepository : EfCoreRepository>(count.HasValue, count.Value) .ToListAsync(GetCancellationToken(cancellationToken)); } - - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetDbSetAsync(), state) - .ToListAsync(GetCancellationToken(cancellationToken)); - } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/EfCoreOpenIddictAuthorizationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/EfCoreOpenIddictAuthorizationRepository.cs index b61770c3e1..e9b4c4b3fb 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/EfCoreOpenIddictAuthorizationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/EfCoreOpenIddictAuthorizationRepository.cs @@ -19,11 +19,6 @@ public class EfCoreOpenIddictAuthorizationRepository : EfCoreRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await query(await GetQueryableAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) @@ -65,12 +60,6 @@ public class EfCoreOpenIddictAuthorizationRepository : EfCoreRepository GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetDbSetAsync(), state) - .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { var query = (await GetDbSetAsync()) @@ -90,12 +79,6 @@ public class EfCoreOpenIddictAuthorizationRepository : EfCoreRepository> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetDbSetAsync(), state) - .ToListAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { var tokenQueryable = (await GetDbContextAsync()).Tokens.AsQueryable(); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictDbContextModelCreatingExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictDbContextModelCreatingExtensions.cs index f03203b155..a32daf43ac 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictDbContextModelCreatingExtensions.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictDbContextModelCreatingExtensions.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using Volo.Abp; using Volo.Abp.EntityFrameworkCore.Modeling; using Volo.Abp.OpenIddict.Applications; using Volo.Abp.OpenIddict.Authorizations; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs index 73537cd7c8..180213efc6 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs @@ -18,11 +18,6 @@ public class EfCoreOpenIddictScopeRepository : EfCoreRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await query(await GetQueryableAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); @@ -43,11 +38,6 @@ public class EfCoreOpenIddictScopeRepository : EfCoreRepository x.Resources.Contains(resource)).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetQueryableAsync(), state).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await (await GetQueryableAsync()) @@ -56,9 +46,4 @@ public class EfCoreOpenIddictScopeRepository : EfCoreRepository>(count.HasValue, count.Value) .ToListAsync(GetCancellationToken(cancellationToken)); } - - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetQueryableAsync(), state).ToListAsync(GetCancellationToken(cancellationToken)); - } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/EfCoreOpenIddictTokenRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/EfCoreOpenIddictTokenRepository.cs index 6642899c63..e08ea1d99f 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/EfCoreOpenIddictTokenRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/EfCoreOpenIddictTokenRepository.cs @@ -38,11 +38,6 @@ public class EfCoreOpenIddictTokenRepository : EfCoreRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await (await GetQueryableAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default) { return await (await GetQueryableAsync()).Where(x => x.Subject == subject && x.ApplicationId == client).ToListAsync(GetCancellationToken(cancellationToken)); @@ -83,11 +78,6 @@ public class EfCoreOpenIddictTokenRepository : EfCoreRepository x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetQueryableAsync(), state).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await (await GetQueryableAsync()) @@ -97,11 +87,6 @@ public class EfCoreOpenIddictTokenRepository : EfCoreRepository> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetQueryableAsync(), state).ToListAsync(GetCancellationToken(cancellationToken)); - } - public async Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { return await (from token in await GetQueryableAsync() diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Applications/MongoOpenIddictApplicationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Applications/MongoOpenIddictApplicationRepository.cs index b7ce27ebf6..fdf7bf9195 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Applications/MongoOpenIddictApplicationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Applications/MongoOpenIddictApplicationRepository.cs @@ -17,13 +17,6 @@ public class MongoOpenIddictApplicationRepository : MongoDbRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(cancellationToken)) - .As>() - .LongCountAsync(GetCancellationToken(cancellationToken)); - } - public async Task FindByClientIdAsync(string clientId, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) @@ -54,9 +47,4 @@ public class MongoOpenIddictApplicationRepository : MongoDbRepository>() .ToListAsync(GetCancellationToken(cancellationToken)); } - - public async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); - } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs index d99ea059f5..a0bd4554cb 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs @@ -19,11 +19,6 @@ public class MongoOpenIddictAuthorizationRepository : MongoDbRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(cancellationToken)).As>().LongCountAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) @@ -60,11 +55,6 @@ public class MongoOpenIddictAuthorizationRepository : MongoDbRepository x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) @@ -74,11 +64,6 @@ public class MongoOpenIddictAuthorizationRepository : MongoDbRepository>().ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { var tokenQueryable = await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs index 5e2c7ec884..413e1a0e4c 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs @@ -17,11 +17,6 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(cancellationToken)).As>().LongCountAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); @@ -46,11 +41,6 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await Queryable.OrderBy((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.Id) @@ -59,9 +49,4 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository>() .ToListAsync(GetCancellationToken(cancellationToken)); } - - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); - } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs index cfc7dae015..632afa511f 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs @@ -39,11 +39,6 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).LongCountAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default) { return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => x.Subject == subject && x.ApplicationId == client) @@ -96,11 +91,6 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await Queryable.OrderBy((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.Id) @@ -110,11 +100,6 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) - { - return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); - } - public async Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { return await (from token in await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)) diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBase.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBase.cs index 2a74ec4a8e..17744e81e4 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBase.cs +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBase.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; -using Volo.Abp; using Volo.Abp.Modularity; using Volo.Abp.Uow; using Volo.Abp.Testing; diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBaseModule.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBaseModule.cs index 95cddaf6d0..38221a6d7a 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBaseModule.cs +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.TestBase/OpenIddictTestBaseModule.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Volo.Abp; using Volo.Abp.Authorization; using Volo.Abp.Autofac; using Volo.Abp.Data;