63 changed files with 3686 additions and 489 deletions
@ -0,0 +1,86 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Collections.Immutable; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace OpenIddict.Abstractions |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to cache applications after retrieving them from the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
public interface IOpenIddictApplicationCache<TApplication> where TApplication : class |
|||
{ |
|||
/// <summary>
|
|||
/// Add the specified application to the cache.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to add to the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
Task AddAsync([NotNull] TApplication application, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its client identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The client identifier associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client application corresponding to the identifier.
|
|||
/// </returns>
|
|||
ValueTask<TApplication> FindByClientIdAsync([NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client application corresponding to the identifier.
|
|||
/// </returns>
|
|||
ValueTask<TApplication> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the applications associated with the specified redirect_uri.
|
|||
/// </summary>
|
|||
/// <param name="address">The redirect_uri associated with the applications.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client applications corresponding to the specified redirect_uri.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TApplication>> FindByPostLogoutRedirectUriAsync( |
|||
[NotNull] string address, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the applications associated with the specified redirect_uri.
|
|||
/// </summary>
|
|||
/// <param name="address">The redirect_uri associated with the applications.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client applications corresponding to the specified redirect_uri.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TApplication>> FindByRedirectUriAsync( |
|||
[NotNull] string address, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified application from the cache.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to remove from the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
Task RemoveAsync([NotNull] TApplication application, CancellationToken cancellationToken); |
|||
} |
|||
} |
|||
@ -0,0 +1,135 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Collections.Immutable; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace OpenIddict.Abstractions |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to cache authorizations after retrieving them from the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
public interface IOpenIddictAuthorizationCache<TAuthorization> where TAuthorization : class |
|||
{ |
|||
/// <summary>
|
|||
/// Add the specified authorization to the cache.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization to add to the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
Task AddAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations corresponding to the specified
|
|||
/// subject and associated with the application identifier.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the subject/client.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the criteria.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, [NotNull] string status, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="type">The authorization type.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the criteria.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, [NotNull] string status, |
|||
[NotNull] string type, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="type">The authorization type.</param>
|
|||
/// <param name="scopes">The minimal scopes associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the criteria.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, [NotNull] string status, |
|||
[NotNull] string type, ImmutableArray<string> scopes, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of authorizations corresponding to the specified application identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The application identifier associated with the authorizations.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the specified application.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TAuthorization>> FindByApplicationIdAsync( |
|||
[NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an authorization using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorization corresponding to the identifier.
|
|||
/// </returns>
|
|||
ValueTask<TAuthorization> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the authorizations corresponding to the specified subject.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the specified subject.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TAuthorization>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified authorization from the cache.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization to remove from the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
Task RemoveAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken); |
|||
} |
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Collections.Immutable; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace OpenIddict.Abstractions |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to cache scopes after retrieving them from the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
public interface IOpenIddictScopeCache<TScope> where TScope : class |
|||
{ |
|||
/// <summary>
|
|||
/// Add the specified scope to the cache.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope to add to the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
Task AddAsync([NotNull] TScope scope, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a scope using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scope corresponding to the identifier.
|
|||
/// </returns>
|
|||
ValueTask<TScope> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a scope using its name.
|
|||
/// </summary>
|
|||
/// <param name="name">The name associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scope corresponding to the specified name.
|
|||
/// </returns>
|
|||
ValueTask<TScope> FindByNameAsync([NotNull] string name, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a list of scopes using their name.
|
|||
/// </summary>
|
|||
/// <param name="names">The names associated with the scopes.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scopes corresponding to the specified names.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TScope>> FindByNamesAsync(ImmutableArray<string> names, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the scopes that contain the specified resource.
|
|||
/// </summary>
|
|||
/// <param name="resource">The resource associated with the scopes.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scopes associated with the specified resource.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TScope>> FindByResourceAsync([NotNull] string resource, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified scope from the cache.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope to remove from the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
Task RemoveAsync([NotNull] TScope scope, CancellationToken cancellationToken); |
|||
} |
|||
} |
|||
@ -0,0 +1,141 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Collections.Immutable; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace OpenIddict.Abstractions |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to cache tokens after retrieving them from the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
public interface IOpenIddictTokenCache<TToken> where TToken : class |
|||
{ |
|||
/// <summary>
|
|||
/// Add the specified token to the cache.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to add to the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
Task AddAsync([NotNull] TToken token, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the tokens corresponding to the specified
|
|||
/// subject and associated with the application identifier.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the token.</param>
|
|||
/// <param name="client">The client associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the subject/client.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TToken>> FindAsync([NotNull] string subject, |
|||
[NotNull] string client, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the tokens matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the token.</param>
|
|||
/// <param name="client">The client associated with the token.</param>
|
|||
/// <param name="status">The token status.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the criteria.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TToken>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the tokens matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the token.</param>
|
|||
/// <param name="client">The client associated with the token.</param>
|
|||
/// <param name="status">The token status.</param>
|
|||
/// <param name="type">The token type.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the criteria.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TToken>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, [NotNull] string type, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified application identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The application identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified application.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TToken>> FindByApplicationIdAsync([NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified authorization identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The authorization identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified authorization.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TToken>> FindByAuthorizationIdAsync([NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a token using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the token corresponding to the unique identifier.
|
|||
/// </returns>
|
|||
ValueTask<TToken> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified reference identifier.
|
|||
/// Note: the reference identifier may be hashed or encrypted for security reasons.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The reference identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified reference identifier.
|
|||
/// </returns>
|
|||
ValueTask<TToken> FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified subject.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified subject.
|
|||
/// </returns>
|
|||
ValueTask<ImmutableArray<TToken>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified token from the cache.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to remove from the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
Task RemoveAsync([NotNull] TToken token, CancellationToken cancellationToken); |
|||
} |
|||
} |
|||
@ -0,0 +1,309 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.Options; |
|||
using OpenIddict.Abstractions; |
|||
|
|||
namespace OpenIddict.Core |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to cache applications after retrieving them from the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
public class OpenIddictApplicationCache<TApplication> : IOpenIddictApplicationCache<TApplication>, IDisposable where TApplication : class |
|||
{ |
|||
private readonly MemoryCache _cache; |
|||
private readonly IOpenIddictApplicationStore<TApplication> _store; |
|||
private readonly IOptions<OpenIddictCoreOptions> _options; |
|||
|
|||
public OpenIddictApplicationCache( |
|||
[NotNull] IOptions<OpenIddictCoreOptions> options, |
|||
[NotNull] IOpenIddictApplicationStoreResolver resolver) |
|||
{ |
|||
_cache = new MemoryCache(new MemoryCacheOptions()); |
|||
_options = options; |
|||
_store = resolver.Get<TApplication>(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Add the specified application to the cache.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to add to the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public async Task AddAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (_cache.Count >= _options.Value.EntityCacheLimit) |
|||
{ |
|||
_cache.Compact(0.25); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = await _store.GetIdAsync(application, cancellationToken) |
|||
})) |
|||
{ |
|||
entry.SetValue(application); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(new |
|||
{ |
|||
Method = nameof(FindByClientIdAsync), |
|||
Identifier = await _store.GetClientIdAsync(application, cancellationToken) |
|||
})) |
|||
{ |
|||
entry.SetValue(application); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disposes the cache held by this instance.
|
|||
/// </summary>
|
|||
public void Dispose() => _cache.Dispose(); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its client identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The client identifier associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client application corresponding to the identifier.
|
|||
/// </returns>
|
|||
public ValueTask<TApplication> FindByClientIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByClientIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out TApplication application)) |
|||
{ |
|||
return new ValueTask<TApplication>(application); |
|||
} |
|||
|
|||
async Task<TApplication> ExecuteAsync() |
|||
{ |
|||
if ((application = await _store.FindByClientIdAsync(identifier, cancellationToken)) != null) |
|||
{ |
|||
await AddAsync(application, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(application); |
|||
} |
|||
|
|||
return application; |
|||
} |
|||
|
|||
return new ValueTask<TApplication>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client application corresponding to the identifier.
|
|||
/// </returns>
|
|||
public ValueTask<TApplication> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out TApplication application)) |
|||
{ |
|||
return new ValueTask<TApplication>(application); |
|||
} |
|||
|
|||
async Task<TApplication> ExecuteAsync() |
|||
{ |
|||
if ((application = await _store.FindByIdAsync(identifier, cancellationToken)) != null) |
|||
{ |
|||
await AddAsync(application, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(application); |
|||
} |
|||
|
|||
return application; |
|||
} |
|||
|
|||
return new ValueTask<TApplication>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the applications associated with the specified post_logout_redirect_uri.
|
|||
/// </summary>
|
|||
/// <param name="address">The post_logout_redirect_uri associated with the applications.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client applications corresponding to the specified post_logout_redirect_uri.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TApplication>> FindByPostLogoutRedirectUriAsync( |
|||
[NotNull] string address, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(address)) |
|||
{ |
|||
throw new ArgumentException("The address cannot be null or empty.", nameof(address)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByPostLogoutRedirectUriAsync), |
|||
Address = address |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TApplication> applications)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TApplication>>(applications); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TApplication>> ExecuteAsync() |
|||
{ |
|||
foreach (var application in (applications = await _store.FindByPostLogoutRedirectUriAsync(address, cancellationToken))) |
|||
{ |
|||
await AddAsync(application, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(applications); |
|||
} |
|||
|
|||
return applications; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TApplication>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the applications associated with the specified redirect_uri.
|
|||
/// </summary>
|
|||
/// <param name="address">The redirect_uri associated with the applications.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client applications corresponding to the specified redirect_uri.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TApplication>> FindByRedirectUriAsync( |
|||
[NotNull] string address, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(address)) |
|||
{ |
|||
throw new ArgumentException("The address cannot be null or empty.", nameof(address)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByRedirectUriAsync), |
|||
Address = address |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TApplication> applications)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TApplication>>(applications); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TApplication>> ExecuteAsync() |
|||
{ |
|||
foreach (var application in (applications = await _store.FindByRedirectUriAsync(address, cancellationToken))) |
|||
{ |
|||
await AddAsync(application, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(applications); |
|||
} |
|||
|
|||
return applications; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TApplication>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified application from the cache.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to remove from the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public async Task RemoveAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByClientIdAsync), |
|||
Identifier = await _store.GetClientIdAsync(application, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = await _store.GetIdAsync(application, cancellationToken) |
|||
}); |
|||
|
|||
foreach (var address in await _store.GetPostLogoutRedirectUrisAsync(application, cancellationToken)) |
|||
{ |
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByPostLogoutRedirectUriAsync), |
|||
Address = address |
|||
}); |
|||
} |
|||
|
|||
foreach (var address in await _store.GetRedirectUrisAsync(application, cancellationToken)) |
|||
{ |
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByRedirectUriAsync), |
|||
Address = address |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,505 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.Options; |
|||
using OpenIddict.Abstractions; |
|||
|
|||
namespace OpenIddict.Core |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to cache authorizations after retrieving them from the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
public class OpenIddictAuthorizationCache<TAuthorization> : IOpenIddictAuthorizationCache<TAuthorization>, IDisposable where TAuthorization : class |
|||
{ |
|||
private readonly MemoryCache _cache; |
|||
private readonly IOpenIddictAuthorizationStore<TAuthorization> _store; |
|||
private readonly IOptions<OpenIddictCoreOptions> _options; |
|||
|
|||
public OpenIddictAuthorizationCache( |
|||
[NotNull] IOptions<OpenIddictCoreOptions> options, |
|||
[NotNull] IOpenIddictAuthorizationStoreResolver resolver) |
|||
{ |
|||
_cache = new MemoryCache(new MemoryCacheOptions()); |
|||
_options = options; |
|||
_store = resolver.Get<TAuthorization>(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Add the specified authorization to the cache.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization to add to the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public async Task AddAsync(TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (_cache.Count >= _options.Value.EntityCacheLimit) |
|||
{ |
|||
_cache.Compact(0.25); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = await _store.GetIdAsync(authorization, cancellationToken) |
|||
})) |
|||
{ |
|||
entry.SetValue(authorization); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disposes the cache held by this instance.
|
|||
/// </summary>
|
|||
public void Dispose() => _cache.Dispose(); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations corresponding to the specified
|
|||
/// subject and associated with the application identifier.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the subject/client.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = subject, |
|||
Client = client |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TAuthorization> authorizations)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TAuthorization>>(authorizations); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TAuthorization>> ExecuteAsync() |
|||
{ |
|||
foreach (var authorization in (authorizations = await _store.FindAsync(subject, client, cancellationToken))) |
|||
{ |
|||
await AddAsync(authorization, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(authorizations); |
|||
} |
|||
|
|||
return authorizations; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TAuthorization>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the criteria.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(status)) |
|||
{ |
|||
throw new ArgumentException("The status cannot be null or empty.", nameof(status)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = subject, |
|||
Client = client, |
|||
Status = status |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TAuthorization> authorizations)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TAuthorization>>(authorizations); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TAuthorization>> ExecuteAsync() |
|||
{ |
|||
foreach (var authorization in (authorizations = await _store.FindAsync(subject, client, status, cancellationToken))) |
|||
{ |
|||
await AddAsync(authorization, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(authorizations); |
|||
} |
|||
|
|||
return authorizations; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TAuthorization>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="type">The authorization type.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the criteria.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, [NotNull] string type, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(status)) |
|||
{ |
|||
throw new ArgumentException("The status cannot be null or empty.", nameof(status)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(type)) |
|||
{ |
|||
throw new ArgumentException("The type cannot be null or empty.", nameof(type)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = subject, |
|||
Client = client, |
|||
Status = status, |
|||
Type = type |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TAuthorization> authorizations)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TAuthorization>>(authorizations); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TAuthorization>> ExecuteAsync() |
|||
{ |
|||
foreach (var authorization in (authorizations = await _store.FindAsync(subject, client, status, type, cancellationToken))) |
|||
{ |
|||
await AddAsync(authorization, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(authorizations); |
|||
} |
|||
|
|||
return authorizations; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TAuthorization>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="type">The authorization type.</param>
|
|||
/// <param name="scopes">The minimal scopes associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the criteria.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, [NotNull] string type, |
|||
ImmutableArray<string> scopes, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(status)) |
|||
{ |
|||
throw new ArgumentException("The status cannot be null or empty.", nameof(status)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(type)) |
|||
{ |
|||
throw new ArgumentException("The type cannot be null or empty.", nameof(type)); |
|||
} |
|||
|
|||
// Note: this method is only partially cached.
|
|||
|
|||
async Task<ImmutableArray<TAuthorization>> ExecuteAsync() |
|||
{ |
|||
var authorizations = await _store.FindAsync(subject, client, status, type, scopes, cancellationToken); |
|||
|
|||
foreach (var authorization in authorizations) |
|||
{ |
|||
await AddAsync(authorization, cancellationToken); |
|||
} |
|||
|
|||
return authorizations; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TAuthorization>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of authorizations corresponding to the specified application identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The application identifier associated with the authorizations.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the specified application.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TAuthorization>> FindByApplicationIdAsync( |
|||
[NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByApplicationIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TAuthorization> authorizations)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TAuthorization>>(authorizations); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TAuthorization>> ExecuteAsync() |
|||
{ |
|||
foreach (var authorization in (authorizations = await _store.FindByApplicationIdAsync(identifier, cancellationToken))) |
|||
{ |
|||
await AddAsync(authorization, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(authorizations); |
|||
} |
|||
|
|||
return authorizations; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TAuthorization>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an authorization using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorization corresponding to the identifier.
|
|||
/// </returns>
|
|||
public ValueTask<TAuthorization> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out TAuthorization authorization)) |
|||
{ |
|||
return new ValueTask<TAuthorization>(authorization); |
|||
} |
|||
|
|||
async Task<TAuthorization> ExecuteAsync() |
|||
{ |
|||
if ((authorization = await _store.FindByIdAsync(identifier, cancellationToken)) != null) |
|||
{ |
|||
await AddAsync(authorization, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(authorization); |
|||
} |
|||
|
|||
return authorization; |
|||
} |
|||
|
|||
return new ValueTask<TAuthorization>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the authorizations corresponding to the specified subject.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the specified subject.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TAuthorization>> FindBySubjectAsync( |
|||
[NotNull] string subject, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindBySubjectAsync), |
|||
Subject = subject |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TAuthorization> authorizations)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TAuthorization>>(authorizations); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TAuthorization>> ExecuteAsync() |
|||
{ |
|||
foreach (var authorization in (authorizations = await _store.FindBySubjectAsync(subject, cancellationToken))) |
|||
{ |
|||
await AddAsync(authorization, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(authorizations); |
|||
} |
|||
|
|||
return authorizations; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TAuthorization>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified authorization from the cache.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization to remove from the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public async Task RemoveAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = await _store.GetSubjectAsync(authorization, cancellationToken), |
|||
Client = await _store.GetApplicationIdAsync(authorization, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = await _store.GetSubjectAsync(authorization, cancellationToken), |
|||
Client = await _store.GetApplicationIdAsync(authorization, cancellationToken), |
|||
Status = await _store.GetStatusAsync(authorization, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = await _store.GetSubjectAsync(authorization, cancellationToken), |
|||
Client = await _store.GetApplicationIdAsync(authorization, cancellationToken), |
|||
Status = await _store.GetStatusAsync(authorization, cancellationToken), |
|||
Type = await _store.GetTypeAsync(authorization, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByApplicationIdAsync), |
|||
Identifier = await _store.GetApplicationIdAsync(authorization, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = await _store.GetIdAsync(authorization, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindBySubjectAsync), |
|||
Subject = await _store.GetSubjectAsync(authorization, cancellationToken) |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,292 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.Options; |
|||
using OpenIddict.Abstractions; |
|||
|
|||
namespace OpenIddict.Core |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to cache scopes after retrieving them from the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
public class OpenIddictScopeCache<TScope> : IOpenIddictScopeCache<TScope>, IDisposable where TScope : class |
|||
{ |
|||
private readonly MemoryCache _cache; |
|||
private readonly IOpenIddictScopeStore<TScope> _store; |
|||
private readonly IOptions<OpenIddictCoreOptions> _options; |
|||
|
|||
public OpenIddictScopeCache( |
|||
[NotNull] IOptions<OpenIddictCoreOptions> options, |
|||
[NotNull] IOpenIddictScopeStoreResolver resolver) |
|||
{ |
|||
_cache = new MemoryCache(new MemoryCacheOptions()); |
|||
_options = options; |
|||
_store = resolver.Get<TScope>(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Add the specified scope to the cache.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope to add to the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public async Task AddAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
if (_cache.Count >= _options.Value.EntityCacheLimit) |
|||
{ |
|||
_cache.Compact(0.25); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = await _store.GetIdAsync(scope, cancellationToken) |
|||
})) |
|||
{ |
|||
entry.SetValue(scope); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(new |
|||
{ |
|||
Method = nameof(FindByNameAsync), |
|||
Name = await _store.GetNameAsync(scope, cancellationToken) |
|||
})) |
|||
{ |
|||
entry.SetValue(scope); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disposes the cache held by this instance.
|
|||
/// </summary>
|
|||
public void Dispose() => _cache.Dispose(); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a scope using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scope corresponding to the identifier.
|
|||
/// </returns>
|
|||
public ValueTask<TScope> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out TScope scope)) |
|||
{ |
|||
return new ValueTask<TScope>(scope); |
|||
} |
|||
|
|||
async Task<TScope> ExecuteAsync() |
|||
{ |
|||
if ((scope = await _store.FindByIdAsync(identifier, cancellationToken)) != null) |
|||
{ |
|||
await AddAsync(scope, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(scope); |
|||
} |
|||
|
|||
return scope; |
|||
} |
|||
|
|||
return new ValueTask<TScope>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a scope using its name.
|
|||
/// </summary>
|
|||
/// <param name="name">The name associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scope corresponding to the specified name.
|
|||
/// </returns>
|
|||
public ValueTask<TScope> FindByNameAsync([NotNull] string name, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(name)) |
|||
{ |
|||
throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByNameAsync), |
|||
Name = name |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out TScope scope)) |
|||
{ |
|||
return new ValueTask<TScope>(scope); |
|||
} |
|||
|
|||
async Task<TScope> ExecuteAsync() |
|||
{ |
|||
if ((scope = await _store.FindByNameAsync(name, cancellationToken)) != null) |
|||
{ |
|||
await AddAsync(scope, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(scope); |
|||
} |
|||
|
|||
return scope; |
|||
} |
|||
|
|||
return new ValueTask<TScope>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a list of scopes using their name.
|
|||
/// </summary>
|
|||
/// <param name="names">The names associated with the scopes.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scopes corresponding to the specified names.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TScope>> FindByNamesAsync(ImmutableArray<string> names, CancellationToken cancellationToken) |
|||
{ |
|||
if (names.IsDefaultOrEmpty) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TScope>>(ImmutableArray.Create<TScope>()); |
|||
} |
|||
|
|||
if (names.Any(name => string.IsNullOrEmpty(name))) |
|||
{ |
|||
throw new ArgumentException("Scope names cannot be null or empty.", nameof(names)); |
|||
} |
|||
|
|||
// Note: this method is only partially cached.
|
|||
|
|||
async Task<ImmutableArray<TScope>> ExecuteAsync() |
|||
{ |
|||
var scopes = await _store.FindByNamesAsync(names, cancellationToken); |
|||
|
|||
foreach (var scope in scopes) |
|||
{ |
|||
await AddAsync(scope, cancellationToken); |
|||
} |
|||
|
|||
return scopes; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TScope>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the scopes that contain the specified resource.
|
|||
/// </summary>
|
|||
/// <param name="resource">The resource associated with the scopes.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scopes associated with the specified resource.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TScope>> FindByResourceAsync([NotNull] string resource, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(resource)) |
|||
{ |
|||
throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByResourceAsync), |
|||
Resource = resource |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TScope> scopes)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TScope>>(scopes); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TScope>> ExecuteAsync() |
|||
{ |
|||
foreach (var scope in (scopes = await _store.FindByResourceAsync(resource, cancellationToken))) |
|||
{ |
|||
await AddAsync(scope, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(scopes); |
|||
} |
|||
|
|||
return scopes; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TScope>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified scope from the cache.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope to remove from the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public async Task RemoveAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = await _store.GetIdAsync(scope, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByNameAsync), |
|||
Name = await _store.GetNameAsync(scope, cancellationToken) |
|||
}); |
|||
|
|||
foreach (var resource in await _store.GetResourcesAsync(scope, cancellationToken)) |
|||
{ |
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByResourceAsync), |
|||
Resource = resource |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,562 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.Options; |
|||
using OpenIddict.Abstractions; |
|||
|
|||
namespace OpenIddict.Core |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to cache tokens after retrieving them from the store.
|
|||
/// </summary>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
public class OpenIddictTokenCache<TToken> : IOpenIddictTokenCache<TToken>, IDisposable where TToken : class |
|||
{ |
|||
private readonly MemoryCache _cache; |
|||
private readonly IOpenIddictTokenStore<TToken> _store; |
|||
private readonly IOptions<OpenIddictCoreOptions> _options; |
|||
|
|||
public OpenIddictTokenCache( |
|||
[NotNull] IOptions<OpenIddictCoreOptions> options, |
|||
[NotNull] IOpenIddictTokenStoreResolver resolver) |
|||
{ |
|||
_cache = new MemoryCache(new MemoryCacheOptions()); |
|||
_options = options; |
|||
_store = resolver.Get<TToken>(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Add the specified token to the cache.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to add to the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public async Task AddAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
if (_cache.Count >= _options.Value.EntityCacheLimit) |
|||
{ |
|||
_cache.Compact(0.25); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = await _store.GetIdAsync(token, cancellationToken) |
|||
})) |
|||
{ |
|||
entry.SetValue(token); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(new |
|||
{ |
|||
Method = nameof(FindByReferenceIdAsync), |
|||
Identifier = await _store.GetReferenceIdAsync(token, cancellationToken) |
|||
})) |
|||
{ |
|||
entry.SetValue(token); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disposes the cache held by this instance.
|
|||
/// </summary>
|
|||
public void Dispose() => _cache.Dispose(); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the tokens corresponding to the specified
|
|||
/// subject and associated with the application identifier.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the token.</param>
|
|||
/// <param name="client">The client associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the subject/client.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TToken>> FindAsync([NotNull] string subject, |
|||
[NotNull] string client, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = subject, |
|||
Client = client |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TToken> tokens)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TToken>>(tokens); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TToken>> ExecuteAsync() |
|||
{ |
|||
foreach (var token in (tokens = await _store.FindAsync(subject, client, cancellationToken))) |
|||
{ |
|||
await AddAsync(token, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(tokens); |
|||
} |
|||
|
|||
return tokens; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TToken>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the tokens matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the token.</param>
|
|||
/// <param name="client">The client associated with the token.</param>
|
|||
/// <param name="status">The token status.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the criteria.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TToken>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(status)) |
|||
{ |
|||
throw new ArgumentException("The status cannot be null or empty.", nameof(status)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = subject, |
|||
Client = client, |
|||
Status = status |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TToken> tokens)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TToken>>(tokens); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TToken>> ExecuteAsync() |
|||
{ |
|||
foreach (var token in (tokens = await _store.FindAsync(subject, client, status, cancellationToken))) |
|||
{ |
|||
await AddAsync(token, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(tokens); |
|||
} |
|||
|
|||
return tokens; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TToken>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the tokens matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the token.</param>
|
|||
/// <param name="client">The client associated with the token.</param>
|
|||
/// <param name="status">The token status.</param>
|
|||
/// <param name="type">The token type.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the criteria.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TToken>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, [NotNull] string type, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(status)) |
|||
{ |
|||
throw new ArgumentException("The status cannot be null or empty.", nameof(status)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(type)) |
|||
{ |
|||
throw new ArgumentException("The type cannot be null or empty.", nameof(type)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = subject, |
|||
Client = client, |
|||
Status = status, |
|||
Type = type |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TToken> tokens)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TToken>>(tokens); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TToken>> ExecuteAsync() |
|||
{ |
|||
foreach (var token in (tokens = await _store.FindAsync(subject, client, status, type, cancellationToken))) |
|||
{ |
|||
await AddAsync(token, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(tokens); |
|||
} |
|||
|
|||
return tokens; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TToken>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified application identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The application identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified application.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TToken>> FindByApplicationIdAsync( |
|||
[NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByApplicationIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TToken> tokens)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TToken>>(tokens); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TToken>> ExecuteAsync() |
|||
{ |
|||
foreach (var token in (tokens = await _store.FindByApplicationIdAsync(identifier, cancellationToken))) |
|||
{ |
|||
await AddAsync(token, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(tokens); |
|||
} |
|||
|
|||
return tokens; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TToken>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified authorization identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The authorization identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified authorization.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TToken>> FindByAuthorizationIdAsync( |
|||
[NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByAuthorizationIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TToken> tokens)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TToken>>(tokens); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TToken>> ExecuteAsync() |
|||
{ |
|||
foreach (var token in (tokens = await _store.FindByAuthorizationIdAsync(identifier, cancellationToken))) |
|||
{ |
|||
await AddAsync(token, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(tokens); |
|||
} |
|||
|
|||
return tokens; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TToken>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a token using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the token corresponding to the unique identifier.
|
|||
/// </returns>
|
|||
public ValueTask<TToken> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out TToken token)) |
|||
{ |
|||
return new ValueTask<TToken>(token); |
|||
} |
|||
|
|||
async Task<TToken> ExecuteAsync() |
|||
{ |
|||
if ((token = await _store.FindByIdAsync(identifier, cancellationToken)) != null) |
|||
{ |
|||
await AddAsync(token, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(token); |
|||
} |
|||
|
|||
return token; |
|||
} |
|||
|
|||
return new ValueTask<TToken>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified reference identifier.
|
|||
/// Note: the reference identifier may be hashed or encrypted for security reasons.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The reference identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified reference identifier.
|
|||
/// </returns>
|
|||
public ValueTask<TToken> FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindByReferenceIdAsync), |
|||
Identifier = identifier |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out TToken token)) |
|||
{ |
|||
return new ValueTask<TToken>(token); |
|||
} |
|||
|
|||
async Task<TToken> ExecuteAsync() |
|||
{ |
|||
if ((token = await _store.FindByReferenceIdAsync(identifier, cancellationToken)) != null) |
|||
{ |
|||
await AddAsync(token, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(token); |
|||
} |
|||
|
|||
return token; |
|||
} |
|||
|
|||
return new ValueTask<TToken>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified subject.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified subject.
|
|||
/// </returns>
|
|||
public ValueTask<ImmutableArray<TToken>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
var parameters = new |
|||
{ |
|||
Method = nameof(FindBySubjectAsync), |
|||
Identifier = subject |
|||
}; |
|||
|
|||
if (_cache.TryGetValue(parameters, out ImmutableArray<TToken> tokens)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<TToken>>(tokens); |
|||
} |
|||
|
|||
async Task<ImmutableArray<TToken>> ExecuteAsync() |
|||
{ |
|||
foreach (var token in (tokens = await _store.FindBySubjectAsync(subject, cancellationToken))) |
|||
{ |
|||
await AddAsync(token, cancellationToken); |
|||
} |
|||
|
|||
using (var entry = _cache.CreateEntry(parameters)) |
|||
{ |
|||
entry.SetValue(tokens); |
|||
} |
|||
|
|||
return tokens; |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<TToken>>(ExecuteAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified token from the cache.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to remove from the cache.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public async Task RemoveAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = await _store.GetSubjectAsync(token, cancellationToken), |
|||
Client = await _store.GetApplicationIdAsync(token, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = await _store.GetSubjectAsync(token, cancellationToken), |
|||
Client = await _store.GetApplicationIdAsync(token, cancellationToken), |
|||
Status = await _store.GetStatusAsync(token, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindAsync), |
|||
Subject = await _store.GetSubjectAsync(token, cancellationToken), |
|||
Client = await _store.GetApplicationIdAsync(token, cancellationToken), |
|||
Status = await _store.GetStatusAsync(token, cancellationToken), |
|||
Type = await _store.GetTypeAsync(token, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByApplicationIdAsync), |
|||
Identifier = await _store.GetApplicationIdAsync(token, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByAuthorizationIdAsync), |
|||
Identifier = await _store.GetAuthorizationIdAsync(token, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByIdAsync), |
|||
Identifier = await _store.GetIdAsync(token, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindByReferenceIdAsync), |
|||
Identifier = await _store.GetReferenceIdAsync(token, cancellationToken) |
|||
}); |
|||
|
|||
_cache.Remove(new |
|||
{ |
|||
Method = nameof(FindBySubjectAsync), |
|||
Subject = await _store.GetSubjectAsync(token, cancellationToken) |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue