Browse Source

Introduce new base classes to make custom stores easier to implement

pull/458/head
Kévin Chalet 9 years ago
parent
commit
936d4988b0
  1. 48
      src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
  2. 46
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  3. 43
      src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
  4. 46
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  5. 32
      src/OpenIddict.Core/Stores/IOpenIddictApplicationStore.cs
  6. 31
      src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs
  7. 27
      src/OpenIddict.Core/Stores/IOpenIddictScopeStore.cs
  8. 29
      src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
  9. 399
      src/OpenIddict.Core/Stores/OpenIddictApplicationStore.cs
  10. 220
      src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
  11. 81
      src/OpenIddict.Core/Stores/OpenIddictScopeStore.cs
  12. 419
      src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
  13. 319
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs
  14. 148
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
  15. 54
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs
  16. 316
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs

48
src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs

@ -39,12 +39,6 @@ namespace OpenIddict.Core
/// </summary>
protected IOpenIddictApplicationStore<TApplication> Store { get; }
/// <summary>
/// Gets the applications as a queryable source,
/// if supported by the underlying store.
/// </summary>
public virtual IQueryable<TApplication> Applications => Store.Applications;
/// <summary>
/// Creates a new application.
/// </summary>
@ -231,6 +225,26 @@ namespace OpenIddict.Core
return Store.FindByRedirectUriAsync(address, cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public virtual Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.GetAsync(query, cancellationToken);
}
/// <summary>
/// Retrieves the client type associated with an application.
/// </summary>
@ -307,7 +321,7 @@ namespace OpenIddict.Core
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens associated with the application.
/// </returns>
public virtual Task<IEnumerable<string>> GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken)
public virtual Task<string[]> GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
@ -400,6 +414,26 @@ namespace OpenIddict.Core
return string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public virtual Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.ListAsync(query, cancellationToken);
}
/// <summary>
/// Updates an existing application.
/// </summary>

46
src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs

@ -37,12 +37,6 @@ namespace OpenIddict.Core
/// </summary>
protected IOpenIddictAuthorizationStore<TAuthorization> Store { get; }
/// <summary>
/// Gets the authorizations as a queryable source,
/// if supported by the underlying store.
/// </summary>
public virtual IQueryable<TAuthorization> Authorizations => Store.Authorizations;
/// <summary>
/// Creates a new authorization.
/// </summary>
@ -110,6 +104,26 @@ namespace OpenIddict.Core
return Store.FindByIdAsync(identifier, cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public virtual Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.GetAsync(query, cancellationToken);
}
/// <summary>
/// Retrieves the unique identifier associated with an authorization.
/// </summary>
@ -129,6 +143,26 @@ namespace OpenIddict.Core
return Store.GetIdAsync(authorization, cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public virtual Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.ListAsync(query, cancellationToken);
}
/// <summary>
/// Revokes an authorization.
/// </summary>

43
src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs

@ -4,7 +4,10 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
@ -35,9 +38,43 @@ namespace OpenIddict.Core
protected IOpenIddictScopeStore<TScope> Store { get; }
/// <summary>
/// Gets the scopes as a queryable source,
/// if supported by the underlying store.
/// Executes the specified query.
/// </summary>
public virtual IQueryable<TScope> Scopes => Store.Scopes;
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public virtual Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.GetAsync(query, cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public virtual Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.ListAsync(query, cancellationToken);
}
}
}

46
src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs

@ -38,12 +38,6 @@ namespace OpenIddict.Core
/// </summary>
protected IOpenIddictTokenStore<TToken> Store { get; }
/// <summary>
/// Gets the tokens as a queryable source,
/// if supported by the underlying store.
/// </summary>
public virtual IQueryable<TToken> Tokens => Store.Tokens;
/// <summary>
/// Creates a new token.
/// </summary>
@ -157,6 +151,26 @@ namespace OpenIddict.Core
return Store.FindBySubjectAsync(subject, cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public virtual Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.GetAsync(query, cancellationToken);
}
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
/// </summary>
@ -356,6 +370,26 @@ namespace OpenIddict.Core
return string.Equals(status, OpenIddictConstants.Statuses.Valid, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public virtual Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.ListAsync(query, cancellationToken);
}
/// <summary>
/// Redeems a token.
/// </summary>

32
src/OpenIddict.Core/Stores/IOpenIddictApplicationStore.cs

@ -4,6 +4,7 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@ -18,11 +19,6 @@ namespace OpenIddict.Core
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
public interface IOpenIddictApplicationStore<TApplication> where TApplication : class
{
/// <summary>
/// Gets the applications as a queryable source, if supported by the store.
/// </summary>
IQueryable<TApplication> Applications { get; }
/// <summary>
/// Creates a new application.
/// </summary>
@ -97,6 +93,18 @@ namespace OpenIddict.Core
/// </returns>
Task<TApplication[]> FindByRedirectUriAsync(string address, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the client identifier associated with an application.
/// </summary>
@ -185,7 +193,19 @@ namespace OpenIddict.Core
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens associated with the application.
/// </returns>
Task<IEnumerable<string>> GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken);
Task<string[]> GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Sets the client secret associated with an application.

31
src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs

@ -4,7 +4,7 @@
* the license and the contributors participating to this project.
*/
using System.Collections.Generic;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -18,11 +18,6 @@ namespace OpenIddict.Core
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
public interface IOpenIddictAuthorizationStore<TAuthorization> where TAuthorization : class
{
/// <summary>
/// Gets the authorizations as a queryable source, if supported by the store.
/// </summary>
IQueryable<TAuthorization> Authorizations { get; }
/// <summary>
/// Creates a new authorization.
/// </summary>
@ -66,6 +61,18 @@ namespace OpenIddict.Core
/// </returns>
Task<TAuthorization> FindAsync(string subject, string client, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the unique identifier associated with an authorization.
/// </summary>
@ -99,6 +106,18 @@ namespace OpenIddict.Core
/// </returns>
Task<string> GetSubjectAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Sets the status associated with an authorization.
/// </summary>

27
src/OpenIddict.Core/Stores/IOpenIddictScopeStore.cs

@ -4,7 +4,11 @@
* the license and the contributors participating to this project.
*/
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace OpenIddict.Core
{
@ -15,8 +19,27 @@ namespace OpenIddict.Core
public interface IOpenIddictScopeStore<TScope> where TScope : class
{
/// <summary>
/// Gets the scopes as a queryable source, if supported by the store.
/// Executes the specified query.
/// </summary>
IQueryable<TScope> Scopes { get; }
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken);
}
}

29
src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs

@ -18,11 +18,6 @@ namespace OpenIddict.Core
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
public interface IOpenIddictTokenStore<TToken> where TToken : class
{
/// <summary>
/// Gets the tokens as a queryable source, if supported by the store.
/// </summary>
IQueryable<TToken> Tokens { get; }
/// <summary>
/// Creates a new token.
/// </summary>
@ -95,6 +90,18 @@ namespace OpenIddict.Core
/// </returns>
Task<TToken[]> FindBySubjectAsync(string subject, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
/// </summary>
@ -194,6 +201,18 @@ namespace OpenIddict.Core
/// </returns>
Task<string> GetTokenTypeAsync([NotNull] TToken token, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Sets the authorization associated with a token.
/// </summary>

399
src/OpenIddict.Core/Stores/OpenIddictApplicationStore.cs

@ -0,0 +1,399 @@
/*
* 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.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using OpenIddict.Models;
namespace OpenIddict.Core
{
/// <summary>
/// Provides methods allowing to manage the applications stored in a database.
/// Note: this base class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
public abstract class OpenIddictApplicationStore<TApplication, TAuthorization, TToken, TKey> : IOpenIddictApplicationStore<TApplication>
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new()
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new()
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new()
where TKey : IEquatable<TKey>
{
/// <summary>
/// Creates a new application.
/// </summary>
/// <param name="application">The application to create.</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, whose result returns the application.
/// </returns>
public abstract Task<TApplication> CreateAsync([NotNull] TApplication application, CancellationToken cancellationToken);
/// <summary>
/// Creates a new application.
/// </summary>
/// <param name="descriptor">The application descriptor.</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, whose result returns the application.
/// </returns>
public abstract Task<TApplication> CreateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken);
/// <summary>
/// Removes an existing application.
/// </summary>
/// <param name="application">The application to delete.</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 abstract Task DeleteAsync([NotNull] TApplication application, 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
public virtual Task<TApplication> FindByIdAsync(string identifier, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(identifier);
return GetAsync(applications => applications.Where(application => application.Id.Equals(key)), 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
public virtual Task<TApplication> FindByClientIdAsync(string identifier, CancellationToken cancellationToken)
{
return GetAsync(applications => applications.Where(application => application.ClientId.Equals(identifier)), cancellationToken);
}
/// <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="Task"/> 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 virtual Task<TApplication[]> FindByLogoutRedirectUriAsync(string address, CancellationToken cancellationToken)
{
return ListAsync(applications => applications.Where(application => application.LogoutRedirectUri == address), 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="Task"/> that can be used to monitor the asynchronous operation, whose result
/// returns the client applications corresponding to the specified redirect_uri.
/// </returns>
public virtual Task<TApplication[]> FindByRedirectUriAsync(string address, CancellationToken cancellationToken)
{
return ListAsync(applications => applications.Where(application => application.RedirectUri == address), cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public abstract Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the client identifier associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the client identifier associated with the application.
/// </returns>
public virtual Task<string> GetClientIdAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.ClientId);
}
/// <summary>
/// Retrieves the client secret associated with an application.
/// Note: depending on the manager used to create the application,
/// the client secret may be hashed for security reasons.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the client secret associated with the application.
/// </returns>
public virtual Task<string> GetClientSecretAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.ClientSecret);
}
/// <summary>
/// Retrieves the client type associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the client type of the application (by default, "public").
/// </returns>
public virtual Task<string> GetClientTypeAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.Type);
}
/// <summary>
/// Retrieves the display name associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the display name associated with the application.
/// </returns>
public virtual Task<string> GetDisplayNameAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.DisplayName);
}
/// <summary>
/// Retrieves the unique identifier associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the unique identifier associated with the application.
/// </returns>
public virtual Task<string> GetIdAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(ConvertIdentifierToString(application.Id));
}
/// <summary>
/// Retrieves the logout callback address associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the post_logout_redirect_uri associated with the application.
/// </returns>
public virtual Task<string> GetLogoutRedirectUriAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.LogoutRedirectUri);
}
/// <summary>
/// Retrieves the callback address associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the redirect_uri associated with the application.
/// </returns>
public virtual Task<string> GetRedirectUriAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.RedirectUri);
}
/// <summary>
/// Retrieves the token identifiers associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the tokens associated with the application.
/// </returns>
public virtual async Task<string[]> GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
var tokens = new List<string>();
foreach (var identifier in await ListAsync(applications =>
from entity in applications
where entity.Id.Equals(application.Id)
from token in entity.Tokens
select token.Id, cancellationToken))
{
tokens.Add(ConvertIdentifierToString(identifier));
}
return tokens.ToArray();
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public abstract Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Sets the client secret associated with an application.
/// Note: depending on the manager used to create the application,
/// the client secret may be hashed for security reasons.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="secret">The client secret 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="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual Task SetClientSecretAsync([NotNull] TApplication application,
[CanBeNull] string secret, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
application.ClientSecret = secret;
return Task.FromResult(0);
}
/// <summary>
/// Sets the client type associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="type">The client type 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="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual Task SetClientTypeAsync([NotNull] TApplication application, [NotNull] string type, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException("The client type cannot be null or empty.", nameof(type));
}
application.Type = type;
return Task.FromResult(0);
}
/// <summary>
/// Updates an existing application.
/// </summary>
/// <param name="application">The application to update.</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 abstract Task UpdateAsync([NotNull] TApplication application, CancellationToken cancellationToken);
/// <summary>
/// Converts the provided identifier to a strongly typed key object.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier)
{
if (string.IsNullOrEmpty(identifier))
{
return default(TKey);
}
return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier);
}
/// <summary>
/// Converts the provided identifier to its string representation.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier)
{
if (Equals(identifier, default(TKey)))
{
return null;
}
return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier);
}
}
}

220
src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs

@ -0,0 +1,220 @@
/*
* 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.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using OpenIddict.Models;
namespace OpenIddict.Core
{
/// <summary>
/// Provides methods allowing to manage the authorizations stored in a database.
/// Note: this base class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
public abstract class OpenIddictAuthorizationStore<TAuthorization, TApplication, TToken, TKey> : IOpenIddictAuthorizationStore<TAuthorization>
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new()
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new()
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new()
where TKey : IEquatable<TKey>
{
/// <summary>
/// Creates a new authorization.
/// </summary>
/// <param name="authorization">The authorization to create.</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, whose result returns the authorization.
/// </returns>
public abstract Task<TAuthorization> CreateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary>
/// Creates a new authorization.
/// </summary>
/// <param name="descriptor">The authorization descriptor.</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, whose result returns the authorization.
/// </returns>
public abstract Task<TAuthorization> CreateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken);
/// <summary>
/// Retrieves an authorization using its associated subject/client.
/// </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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization corresponding to the subject/client.
/// </returns>
public virtual Task<TAuthorization> FindAsync(string subject, string client, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(client);
return GetAsync(authorizations =>
from authorization in authorizations
where authorization.Application.Id.Equals(key)
where authorization.Subject == subject
select authorization, 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization corresponding to the identifier.
/// </returns>
public virtual Task<TAuthorization> FindByIdAsync(string identifier, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(identifier);
return GetAsync(authorizations => authorizations.Where(authorization => authorization.Id.Equals(key)), cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public abstract Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the unique identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</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,
/// whose result returns the unique identifier associated with the authorization.
/// </returns>
public virtual Task<string> GetIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Task.FromResult(ConvertIdentifierToString(authorization.Id));
}
/// <summary>
/// Retrieves the status associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</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,
/// whose result returns the status associated with the specified authorization.
/// </returns>
public virtual Task<string> GetStatusAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
return Task.FromResult(authorization.Status);
}
/// <summary>
/// Retrieves the subject associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</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,
/// whose result returns the subject associated with the specified authorization.
/// </returns>
public virtual Task<string> GetSubjectAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Task.FromResult(authorization.Subject);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public abstract Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Sets the status associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="status">The status 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="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual Task SetStatusAsync([NotNull] TAuthorization authorization, [NotNull] string status, CancellationToken cancellationToken)
{
authorization.Status = status;
return Task.CompletedTask;
}
/// <summary>
/// Updates an existing authorization.
/// </summary>
/// <param name="authorization">The authorization to update.</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 abstract Task UpdateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary>
/// Converts the provided identifier to a strongly typed key object.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier)
{
if (string.IsNullOrEmpty(identifier))
{
return default(TKey);
}
return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier);
}
/// <summary>
/// Converts the provided identifier to its string representation.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier)
{
if (Equals(identifier, default(TKey)))
{
return null;
}
return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier);
}
}
}

81
src/OpenIddict.Core/Stores/OpenIddictScopeStore.cs

@ -0,0 +1,81 @@
/*
* 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.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using OpenIddict.Models;
namespace OpenIddict.Core
{
/// <summary>
/// Provides methods allowing to manage the scopes stored in a database.
/// Note: this base class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
public abstract class OpenIddictScopeStore<TScope, TKey> : IOpenIddictScopeStore<TScope>
where TScope : OpenIddictScope<TKey>, new()
where TKey : IEquatable<TKey>
{
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public abstract Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public abstract Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Converts the provided identifier to a strongly typed key object.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier)
{
if (string.IsNullOrEmpty(identifier))
{
return default(TKey);
}
return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier);
}
/// <summary>
/// Converts the provided identifier to its string representation.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier)
{
if (Equals(identifier, default(TKey)))
{
return null;
}
return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier);
}
}
}

419
src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs

@ -0,0 +1,419 @@
/*
* 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.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using OpenIddict.Models;
namespace OpenIddict.Core
{
/// <summary>
/// Provides methods allowing to manage the tokens stored in a database.
/// Note: this base class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
public abstract class OpenIddictTokenStore<TToken, TApplication, TAuthorization, TKey> : IOpenIddictTokenStore<TToken>
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new()
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new()
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new()
where TKey : IEquatable<TKey>
{
/// <summary>
/// Creates a new token.
/// </summary>
/// <param name="token">The token to create.</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, whose result returns the token.
/// </returns>
public abstract Task<TToken> CreateAsync([NotNull] TToken token, CancellationToken cancellationToken);
/// <summary>
/// Creates a new token, which is associated with a particular subject.
/// </summary>
/// <param name="descriptor">The token descriptor.</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, whose result returns the token.
/// </returns>
public abstract Task<TToken> CreateAsync([NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken);
/// <summary>
/// Removes a token.
/// </summary>
/// <param name="token">The token to delete.</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 abstract Task DeleteAsync([NotNull] TToken token, 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified authorization.
/// </returns>
public virtual Task<TToken[]> FindByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(identifier);
return ListAsync(tokens => tokens.Where(token => token.Authorization.Id.Equals(key)), cancellationToken);
}
/// <summary>
/// Retrieves the list of tokens corresponding to the specified hash.
/// </summary>
/// <param name="hash">The hashed crypto-secure random 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified hash.
/// </returns>
public virtual Task<TToken> FindByHashAsync(string hash, CancellationToken cancellationToken)
{
return GetAsync(tokens => tokens.Where(token => token.Hash == hash), cancellationToken);
}
/// <summary>
/// Retrieves an 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the token corresponding to the unique identifier.
/// </returns>
public virtual Task<TToken> FindByIdAsync(string identifier, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(identifier);
return GetAsync(tokens => tokens.Where(token => token.Id.Equals(key)), 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified subject.
/// </returns>
public virtual Task<TToken[]> FindBySubjectAsync(string subject, CancellationToken cancellationToken)
{
return ListAsync(tokens => tokens.Where(token => token.Subject == subject), cancellationToken);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public abstract Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the authorization identifier associated with the token.
/// </returns>
public virtual async Task<string> GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.Authorization != null)
{
return ConvertIdentifierToString(token.Authorization.Id);
}
var key = await GetAsync(tokens =>
from element in tokens
where element.Id.Equals(token.Id)
select element.Authorization.Id, cancellationToken);
return ConvertIdentifierToString(key);
}
/// <summary>
/// Retrieves the ciphertext associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the ciphertext associated with the specified token.
/// </returns>
public virtual Task<string> GetCiphertextAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Ciphertext);
}
/// <summary>
/// Retrieves the creation date associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the creation date associated with the specified token.
/// </returns>
public virtual Task<DateTimeOffset?> GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.CreationDate);
}
/// <summary>
/// Retrieves the expiration date associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the expiration date associated with the specified token.
/// </returns>
public virtual Task<DateTimeOffset?> GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.ExpirationDate);
}
/// <summary>
/// Retrieves the hashed identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the hashed identifier associated with the specified token.
/// </returns>
public virtual Task<string> GetHashAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Hash);
}
/// <summary>
/// Retrieves the unique identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the unique identifier associated with the token.
/// </returns>
public virtual Task<string> GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(ConvertIdentifierToString(token.Id));
}
/// <summary>
/// Retrieves the status associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the status associated with the specified token.
/// </returns>
public virtual Task<string> GetStatusAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Status);
}
/// <summary>
/// Retrieves the subject associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the subject associated with the specified token.
/// </returns>
public virtual Task<string> GetSubjectAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Subject);
}
/// <summary>
/// Retrieves the token type associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the token type associated with the specified token.
/// </returns>
public virtual Task<string> GetTokenTypeAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Type);
}
/// <summary>
/// Executes the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public abstract Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Sets the authorization associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <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="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public abstract Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Sets the client application associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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 abstract Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary>
/// Sets the expiration date associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="date">The date on which the token will no longer be considered valid.</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 virtual Task SetExpirationDateAsync([NotNull] TToken token,
[CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken)
{
token.ExpirationDate = date;
return Task.CompletedTask;
}
/// <summary>
/// Sets the status associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="status">The status 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="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual Task SetStatusAsync([NotNull] TToken token, [NotNull] string status, CancellationToken cancellationToken)
{
token.Status = status;
return Task.CompletedTask;
}
/// <summary>
/// Updates an existing token.
/// </summary>
/// <param name="token">The token to update.</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 abstract Task UpdateAsync([NotNull] TToken token, CancellationToken cancellationToken);
/// <summary>
/// Converts the provided identifier to a strongly typed key object.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier)
{
if (string.IsNullOrEmpty(identifier))
{
return default(TKey);
}
return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier);
}
/// <summary>
/// Converts the provided identifier to its string representation.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier)
{
if (Equals(identifier, default(TKey)))
{
return null;
}
return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier);
}
}
}

319
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs

@ -5,8 +5,6 @@
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -19,6 +17,7 @@ namespace OpenIddict.EntityFrameworkCore
{
/// <summary>
/// Provides methods allowing to manage the applications stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
public class OpenIddictApplicationStore<TContext> : OpenIddictApplicationStore<OpenIddictApplication,
@ -31,6 +30,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <summary>
/// Provides methods allowing to manage the applications stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
@ -45,13 +45,15 @@ namespace OpenIddict.EntityFrameworkCore
/// <summary>
/// Provides methods allowing to manage the applications stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
public class OpenIddictApplicationStore<TApplication, TAuthorization, TToken, TContext, TKey> : IOpenIddictApplicationStore<TApplication>
public class OpenIddictApplicationStore<TApplication, TAuthorization, TToken, TContext, TKey> :
OpenIddictApplicationStore<TApplication, TAuthorization, TToken, TKey>
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new()
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new()
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new()
@ -78,11 +80,6 @@ namespace OpenIddict.EntityFrameworkCore
/// </summary>
protected DbSet<TApplication> Applications => Context.Set<TApplication>();
/// <summary>
/// Gets the applications as a queryable source, if supported by the store.
/// </summary>
IQueryable<TApplication> IOpenIddictApplicationStore<TApplication>.Applications => Applications;
/// <summary>
/// Creates a new application.
/// </summary>
@ -91,7 +88,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the application.
/// </returns>
public virtual async Task<TApplication> CreateAsync([NotNull] TApplication application, CancellationToken cancellationToken)
public override async Task<TApplication> CreateAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
@ -113,7 +110,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the application.
/// </returns>
public Task<TApplication> CreateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken)
public override Task<TApplication> CreateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken)
{
if (descriptor == null)
{
@ -141,7 +138,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async Task DeleteAsync([NotNull] TApplication application, CancellationToken cancellationToken)
public override async Task DeleteAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
@ -159,277 +156,43 @@ namespace OpenIddict.EntityFrameworkCore
}
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
public virtual Task<TApplication> FindByIdAsync(string identifier, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(identifier);
return Applications.SingleOrDefaultAsync(application => application.Id.Equals(key), 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
public virtual Task<TApplication> FindByClientIdAsync(string identifier, CancellationToken cancellationToken)
{
return Applications.SingleOrDefaultAsync(application => application.ClientId.Equals(identifier), cancellationToken);
}
/// <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="Task"/> 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 virtual Task<TApplication[]> FindByLogoutRedirectUriAsync(string address, CancellationToken cancellationToken)
{
return Applications.Where(application => application.LogoutRedirectUri == address).ToArrayAsync(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="Task"/> that can be used to monitor the asynchronous operation, whose result
/// returns the client applications corresponding to the specified redirect_uri.
/// </returns>
public virtual Task<TApplication[]> FindByRedirectUriAsync(string address, CancellationToken cancellationToken)
{
return Applications.Where(application => application.RedirectUri == address).ToArrayAsync(cancellationToken);
}
/// <summary>
/// Retrieves the client identifier associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the client identifier associated with the application.
/// </returns>
public virtual Task<string> GetClientIdAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.ClientId);
}
/// <summary>
/// Retrieves the client secret associated with an application.
/// Note: depending on the manager used to create the application,
/// the client secret may be hashed for security reasons.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the client secret associated with the application.
/// </returns>
public virtual Task<string> GetClientSecretAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.ClientSecret);
}
/// <summary>
/// Retrieves the client type associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the client type of the application (by default, "public").
/// </returns>
public virtual Task<string> GetClientTypeAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.Type);
}
/// <summary>
/// Retrieves the display name associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the display name associated with the application.
/// </returns>
public virtual Task<string> GetDisplayNameAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.DisplayName);
}
/// <summary>
/// Retrieves the unique identifier associated with an application.
/// Executes the specified query.
/// </summary>
/// <param name="application">The application.</param>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the unique identifier associated with the application.
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public virtual Task<string> GetIdAsync([NotNull] TApplication application, CancellationToken cancellationToken)
public override Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (application == null)
if (query == null)
{
throw new ArgumentNullException(nameof(application));
throw new ArgumentNullException(nameof(query));
}
return Task.FromResult(ConvertIdentifierToString(application.Id));
return query.Invoke(Applications).SingleOrDefaultAsync(cancellationToken);
}
/// <summary>
/// Retrieves the logout callback address associated with an application.
/// Executes the specified query.
/// </summary>
/// <param name="application">The application.</param>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the post_logout_redirect_uri associated with the application.
/// </returns>
public virtual Task<string> GetLogoutRedirectUriAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.LogoutRedirectUri);
}
/// <summary>
/// Retrieves the callback address associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the redirect_uri associated with the application.
/// </returns>
public virtual Task<string> GetRedirectUriAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
return Task.FromResult(application.RedirectUri);
}
/// <summary>
/// Retrieves the token identifiers associated with an application.
/// </summary>
/// <param name="application">The application.</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,
/// whose result returns the tokens associated with the application.
/// </returns>
public virtual async Task<IEnumerable<string>> GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
var query = from entity in Applications
where entity.Id.Equals(application.Id)
from token in entity.Tokens
select token.Id;
var tokens = new List<string>();
foreach (var identifier in await query.ToArrayAsync())
{
tokens.Add(ConvertIdentifierToString(identifier));
}
return tokens;
}
/// <summary>
/// Sets the client secret associated with an application.
/// Note: depending on the manager used to create the application,
/// the client secret may be hashed for security reasons.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="secret">The client secret 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="Task"/> that can be used to monitor the asynchronous operation.
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public virtual Task SetClientSecretAsync([NotNull] TApplication application,
[CanBeNull] string secret, CancellationToken cancellationToken)
public override Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (application == null)
if (query == null)
{
throw new ArgumentNullException(nameof(application));
throw new ArgumentNullException(nameof(query));
}
application.ClientSecret = secret;
return Task.FromResult(0);
}
/// <summary>
/// Sets the client type associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="type">The client type 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="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual Task SetClientTypeAsync([NotNull] TApplication application, [NotNull] string type, CancellationToken cancellationToken)
{
if (application == null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException("The client type cannot be null or empty.", nameof(type));
}
application.Type = type;
return Task.FromResult(0);
return query.Invoke(Applications).ToArrayAsync(cancellationToken);
}
/// <summary>
@ -440,7 +203,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async Task UpdateAsync([NotNull] TApplication application, CancellationToken cancellationToken)
public override async Task UpdateAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{
if (application == null)
{
@ -457,37 +220,5 @@ namespace OpenIddict.EntityFrameworkCore
catch (DbUpdateConcurrencyException) { }
}
/// <summary>
/// Converts the provided identifier to a strongly typed key object.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier)
{
if (string.IsNullOrEmpty(identifier))
{
return default(TKey);
}
return (TKey) TypeDescriptor.GetConverter(typeof(TKey))
.ConvertFromInvariantString(identifier);
}
/// <summary>
/// Converts the provided identifier to its string representation.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier)
{
if (Equals(identifier, default(TKey)))
{
return null;
}
return TypeDescriptor.GetConverter(typeof(TKey))
.ConvertToInvariantString(identifier);
}
}
}

148
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs

@ -5,8 +5,6 @@
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -19,6 +17,7 @@ namespace OpenIddict.EntityFrameworkCore
{
/// <summary>
/// Provides methods allowing to manage the authorizations stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
public class OpenIddictAuthorizationStore<TContext> : OpenIddictAuthorizationStore<OpenIddictAuthorization,
@ -31,6 +30,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <summary>
/// Provides methods allowing to manage the authorizations stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
@ -45,13 +45,15 @@ namespace OpenIddict.EntityFrameworkCore
/// <summary>
/// Provides methods allowing to manage the authorizations stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
public class OpenIddictAuthorizationStore<TAuthorization, TApplication, TToken, TContext, TKey> : IOpenIddictAuthorizationStore<TAuthorization>
public class OpenIddictAuthorizationStore<TAuthorization, TApplication, TToken, TContext, TKey> :
OpenIddictAuthorizationStore<TAuthorization, TApplication, TToken, TKey>
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new()
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new()
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new()
@ -83,11 +85,6 @@ namespace OpenIddict.EntityFrameworkCore
/// </summary>
protected DbSet<TAuthorization> Authorizations => Context.Set<TAuthorization>();
/// <summary>
/// Gets the authorizations as a queryable source, if supported by the store.
/// </summary>
IQueryable<TAuthorization> IOpenIddictAuthorizationStore<TAuthorization>.Authorizations => Authorizations;
/// <summary>
/// Creates a new authorization.
/// </summary>
@ -96,7 +93,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the authorization.
/// </returns>
public virtual async Task<TAuthorization> CreateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
public override async Task<TAuthorization> CreateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
@ -118,7 +115,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the authorization.
/// </returns>
public virtual async Task<TAuthorization> CreateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken)
public override async Task<TAuthorization> CreateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken)
{
if (descriptor == null)
{
@ -149,108 +146,43 @@ namespace OpenIddict.EntityFrameworkCore
}
/// <summary>
/// Retrieves an authorization using its associated subject/client.
/// </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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization corresponding to the subject/client.
/// </returns>
public virtual Task<TAuthorization> FindAsync(string subject, string client, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(client);
return (from application in Applications
where application.Id.Equals(key)
from authorization in application.Authorizations
where authorization.Subject == subject
select authorization).FirstOrDefaultAsync();
}
/// <summary>
/// Retrieves an authorization using its unique identifier.
/// Executes the specified query.
/// </summary>
/// <param name="identifier">The unique identifier associated with the authorization.</param>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the authorization corresponding to the identifier.
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public virtual Task<TAuthorization> FindByIdAsync(string identifier, CancellationToken cancellationToken)
public override Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(identifier);
return Authorizations.SingleOrDefaultAsync(authorization => authorization.Id.Equals(key), cancellationToken);
}
/// <summary>
/// Retrieves the unique identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</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,
/// whose result returns the unique identifier associated with the authorization.
/// </returns>
public virtual Task<string> GetIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
if (query == null)
{
throw new ArgumentNullException(nameof(authorization));
throw new ArgumentNullException(nameof(query));
}
return Task.FromResult(ConvertIdentifierToString(authorization.Id));
}
/// <summary>
/// Retrieves the status associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</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,
/// whose result returns the status associated with the specified authorization.
/// </returns>
public virtual Task<string> GetStatusAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
return Task.FromResult(authorization.Status);
return query.Invoke(Authorizations).SingleOrDefaultAsync(cancellationToken);
}
/// <summary>
/// Retrieves the subject associated with an authorization.
/// Executes the specified query.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the subject associated with the specified authorization.
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public virtual Task<string> GetSubjectAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
public override Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (authorization == null)
if (query == null)
{
throw new ArgumentNullException(nameof(authorization));
throw new ArgumentNullException(nameof(query));
}
return Task.FromResult(authorization.Subject);
}
/// <summary>
/// Sets the status associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="status">The status 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="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual Task SetStatusAsync([NotNull] TAuthorization authorization, [NotNull] string status, CancellationToken cancellationToken)
{
authorization.Status = status;
return Task.CompletedTask;
return query.Invoke(Authorizations).ToArrayAsync(cancellationToken);
}
/// <summary>
@ -261,7 +193,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async Task UpdateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
public override async Task UpdateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
Context.Attach(authorization);
@ -274,37 +206,5 @@ namespace OpenIddict.EntityFrameworkCore
catch (DbUpdateConcurrencyException) { }
}
/// <summary>
/// Converts the provided identifier to a strongly typed key object.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier)
{
if (string.IsNullOrEmpty(identifier))
{
return default(TKey);
}
return (TKey) TypeDescriptor.GetConverter(typeof(TKey))
.ConvertFromInvariantString(identifier);
}
/// <summary>
/// Converts the provided identifier to its string representation.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier)
{
if (Equals(identifier, default(TKey)))
{
return null;
}
return TypeDescriptor.GetConverter(typeof(TKey))
.ConvertToInvariantString(identifier);
}
}
}

54
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs

@ -5,17 +5,18 @@
*/
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using OpenIddict.Core;
using OpenIddict.Models;
namespace OpenIddict.EntityFrameworkCore
{
/// <summary>
/// Provides methods allowing to manage the scopes stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
public class OpenIddictScopeStore<TContext> : OpenIddictScopeStore<OpenIddictScope, TContext, string>
@ -26,6 +27,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <summary>
/// Provides methods allowing to manage the scopes stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
@ -38,11 +40,12 @@ namespace OpenIddict.EntityFrameworkCore
/// <summary>
/// Provides methods allowing to manage the scopes stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
public class OpenIddictScopeStore<TScope, TContext, TKey> : IOpenIddictScopeStore<TScope>
public class OpenIddictScopeStore<TScope, TContext, TKey> : Core.OpenIddictScopeStore<TScope, TKey>
where TScope : OpenIddictScope<TKey>, new()
where TContext : DbContext
where TKey : IEquatable<TKey>
@ -68,40 +71,43 @@ namespace OpenIddict.EntityFrameworkCore
protected DbSet<TScope> Scopes => Context.Set<TScope>();
/// <summary>
/// Gets the scopes as a queryable source, if supported by the store.
/// Executes the specified query.
/// </summary>
IQueryable<TScope> IOpenIddictScopeStore<TScope>.Scopes => Scopes;
/// <summary>
/// Converts the provided identifier to a strongly typed key object.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier)
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public override Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
if (query == null)
{
return default(TKey);
throw new ArgumentNullException(nameof(query));
}
return (TKey) TypeDescriptor.GetConverter(typeof(TKey))
.ConvertFromInvariantString(identifier);
return query.Invoke(Scopes).SingleOrDefaultAsync(cancellationToken);
}
/// <summary>
/// Converts the provided identifier to its string representation.
/// Executes the specified query.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier)
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public override Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (Equals(identifier, default(TKey)))
if (query == null)
{
return null;
throw new ArgumentNullException(nameof(query));
}
return TypeDescriptor.GetConverter(typeof(TKey))
.ConvertToInvariantString(identifier);
return query.Invoke(Scopes).ToArrayAsync(cancellationToken);
}
}
}

316
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs

@ -5,7 +5,6 @@
*/
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -18,6 +17,7 @@ namespace OpenIddict.EntityFrameworkCore
{
/// <summary>
/// Provides methods allowing to manage the tokens stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
public class OpenIddictTokenStore<TContext> : OpenIddictTokenStore<OpenIddictToken,
@ -30,6 +30,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <summary>
/// Provides methods allowing to manage the tokens stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
@ -44,13 +45,15 @@ namespace OpenIddict.EntityFrameworkCore
/// <summary>
/// Provides methods allowing to manage the tokens stored in a database.
/// Note: this class can only be used with the default OpenIddict entities.
/// </summary>
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
/// <typeparam name="TContext">The type of the Entity Framework database context.</typeparam>
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
public class OpenIddictTokenStore<TToken, TApplication, TAuthorization, TContext, TKey> : IOpenIddictTokenStore<TToken>
public class OpenIddictTokenStore<TToken, TApplication, TAuthorization, TContext, TKey> :
OpenIddictTokenStore<TToken, TApplication, TAuthorization, TKey>
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new()
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new()
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new()
@ -87,11 +90,6 @@ namespace OpenIddict.EntityFrameworkCore
/// </summary>
protected DbSet<TToken> Tokens => Context.Set<TToken>();
/// <summary>
/// Gets the tokens as a queryable source, if supported by the store.
/// </summary>
IQueryable<TToken> IOpenIddictTokenStore<TToken>.Tokens => Tokens;
/// <summary>
/// Creates a new token.
/// </summary>
@ -100,7 +98,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the token.
/// </returns>
public virtual async Task<TToken> CreateAsync([NotNull] TToken token, CancellationToken cancellationToken)
public override async Task<TToken> CreateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
@ -122,7 +120,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the token.
/// </returns>
public virtual async Task<TToken> CreateAsync([NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken)
public override async Task<TToken> CreateAsync([NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken)
{
if (descriptor == null)
{
@ -176,7 +174,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <param name="token">The token to delete.</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 virtual async Task DeleteAsync([NotNull] TToken token, CancellationToken cancellationToken)
public override async Task DeleteAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
@ -194,238 +192,43 @@ namespace OpenIddict.EntityFrameworkCore
}
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified authorization.
/// </returns>
public virtual Task<TToken[]> FindByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(identifier);
return Tokens.Where(token => token.Authorization.Id.Equals(key)).ToArrayAsync(cancellationToken);
}
/// <summary>
/// Retrieves the list of tokens corresponding to the specified hash.
/// </summary>
/// <param name="hash">The hashed crypto-secure random 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified hash.
/// </returns>
public virtual Task<TToken> FindByHashAsync(string hash, CancellationToken cancellationToken)
{
return Tokens.SingleOrDefaultAsync(token => token.Hash == hash, cancellationToken);
}
/// <summary>
/// Retrieves an 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the token corresponding to the unique identifier.
/// </returns>
public virtual Task<TToken> FindByIdAsync(string identifier, CancellationToken cancellationToken)
{
var key = ConvertIdentifierFromString(identifier);
return Tokens.SingleOrDefaultAsync(token => token.Id.Equals(key), 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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified subject.
/// </returns>
public virtual Task<TToken[]> FindBySubjectAsync(string subject, CancellationToken cancellationToken)
{
return Tokens.Where(token => token.Subject == subject).ToArrayAsync();
}
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the authorization identifier associated with the token.
/// </returns>
public virtual async Task<string> GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
var key = await (from authorization in Authorizations
where authorization.Tokens.Any(entity => entity.Id.Equals(token.Id))
select authorization.Id).SingleOrDefaultAsync();
return ConvertIdentifierToString(key);
}
/// <summary>
/// Retrieves the ciphertext associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the ciphertext associated with the specified token.
/// </returns>
public virtual Task<string> GetCiphertextAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Ciphertext);
}
/// <summary>
/// Retrieves the creation date associated with a token.
/// Executes the specified query.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the creation date associated with the specified token.
/// </returns>
public virtual Task<DateTimeOffset?> GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.CreationDate);
}
/// <summary>
/// Retrieves the expiration date associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the expiration date associated with the specified token.
/// whose result returns the single element returned when executing the specified query.
/// </returns>
public virtual Task<DateTimeOffset?> GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
public override Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (token == null)
if (query == null)
{
throw new ArgumentNullException(nameof(token));
throw new ArgumentNullException(nameof(query));
}
return Task.FromResult(token.ExpirationDate);
return query.Invoke(Tokens).SingleOrDefaultAsync(cancellationToken);
}
/// <summary>
/// Retrieves the hashed identifier associated with a token.
/// Executes the specified query.
/// </summary>
/// <param name="token">The token.</param>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</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,
/// whose result returns the hashed identifier associated with the specified token.
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
public virtual Task<string> GetHashAsync([NotNull] TToken token, CancellationToken cancellationToken)
public override Task<TResult[]> ListAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (token == null)
if (query == null)
{
throw new ArgumentNullException(nameof(token));
throw new ArgumentNullException(nameof(query));
}
return Task.FromResult(token.Hash);
}
/// <summary>
/// Retrieves the unique identifier associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the unique identifier associated with the token.
/// </returns>
public virtual Task<string> GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(ConvertIdentifierToString(token.Id));
}
/// <summary>
/// Retrieves the status associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the status associated with the specified token.
/// </returns>
public virtual Task<string> GetStatusAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Status);
}
/// <summary>
/// Retrieves the subject associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the subject associated with the specified token.
/// </returns>
public virtual Task<string> GetSubjectAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Subject);
}
/// <summary>
/// Retrieves the token type associated with a token.
/// </summary>
/// <param name="token">The token.</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,
/// whose result returns the token type associated with the specified token.
/// </returns>
public virtual Task<string> GetTokenTypeAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Task.FromResult(token.Type);
return query.Invoke(Tokens).ToArrayAsync(cancellationToken);
}
/// <summary>
@ -437,7 +240,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
public override async Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
@ -480,7 +283,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
public override async Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
@ -514,39 +317,6 @@ namespace OpenIddict.EntityFrameworkCore
}
}
/// <summary>
/// Sets the expiration date associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="date">The date on which the token will no longer be considered valid.</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 virtual Task SetExpirationDateAsync([NotNull] TToken token,
[CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken)
{
token.ExpirationDate = date;
return Task.CompletedTask;
}
/// <summary>
/// Sets the status associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="status">The status 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="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual Task SetStatusAsync([NotNull] TToken token, [NotNull] string status, CancellationToken cancellationToken)
{
token.Status = status;
return Task.CompletedTask;
}
/// <summary>
/// Updates an existing token.
/// </summary>
@ -555,7 +325,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async Task UpdateAsync([NotNull] TToken token, CancellationToken cancellationToken)
public override async Task UpdateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
@ -572,37 +342,5 @@ namespace OpenIddict.EntityFrameworkCore
catch (DbUpdateConcurrencyException) { }
}
/// <summary>
/// Converts the provided identifier to a strongly typed key object.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier)
{
if (string.IsNullOrEmpty(identifier))
{
return default(TKey);
}
return (TKey) TypeDescriptor.GetConverter(typeof(TKey))
.ConvertFromInvariantString(identifier);
}
/// <summary>
/// Converts the provided identifier to its string representation.
/// </summary>
/// <param name="identifier">The identifier to convert.</param>
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier)
{
if (Equals(identifier, default(TKey)))
{
return null;
}
return TypeDescriptor.GetConverter(typeof(TKey))
.ConvertToInvariantString(identifier);
}
}
}
Loading…
Cancel
Save