diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs index 6bc8b742..6eb37ef1 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs @@ -39,12 +39,6 @@ namespace OpenIddict.Core /// protected IOpenIddictApplicationStore Store { get; } - /// - /// Gets the applications as a queryable source, - /// if supported by the underlying store. - /// - public virtual IQueryable Applications => Store.Applications; - /// /// Creates a new application. /// @@ -231,6 +225,26 @@ namespace OpenIddict.Core return Store.FindByRedirectUriAsync(address, cancellationToken); } + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public virtual Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) + { + if (query == null) + { + throw new ArgumentNullException(nameof(query)); + } + + return Store.GetAsync(query, cancellationToken); + } + /// /// Retrieves the client type associated with an application. /// @@ -307,7 +321,7 @@ namespace OpenIddict.Core /// A that can be used to monitor the asynchronous operation, /// whose result returns the tokens associated with the application. /// - public virtual Task> GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken) + public virtual Task 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); } + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public virtual Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) + { + if (query == null) + { + throw new ArgumentNullException(nameof(query)); + } + + return Store.ListAsync(query, cancellationToken); + } + /// /// Updates an existing application. /// diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs index e0be8bdd..44737b82 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs @@ -37,12 +37,6 @@ namespace OpenIddict.Core /// protected IOpenIddictAuthorizationStore Store { get; } - /// - /// Gets the authorizations as a queryable source, - /// if supported by the underlying store. - /// - public virtual IQueryable Authorizations => Store.Authorizations; - /// /// Creates a new authorization. /// @@ -110,6 +104,26 @@ namespace OpenIddict.Core return Store.FindByIdAsync(identifier, cancellationToken); } + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public virtual Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) + { + if (query == null) + { + throw new ArgumentNullException(nameof(query)); + } + + return Store.GetAsync(query, cancellationToken); + } + /// /// Retrieves the unique identifier associated with an authorization. /// @@ -129,6 +143,26 @@ namespace OpenIddict.Core return Store.GetIdAsync(authorization, cancellationToken); } + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public virtual Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) + { + if (query == null) + { + throw new ArgumentNullException(nameof(query)); + } + + return Store.ListAsync(query, cancellationToken); + } + /// /// Revokes an authorization. /// diff --git a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs index b001add4..10448be4 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs +++ b/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 Store { get; } /// - /// Gets the scopes as a queryable source, - /// if supported by the underlying store. + /// Executes the specified query. /// - public virtual IQueryable Scopes => Store.Scopes; + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public virtual Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) + { + if (query == null) + { + throw new ArgumentNullException(nameof(query)); + } + + return Store.GetAsync(query, cancellationToken); + } + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public virtual Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) + { + if (query == null) + { + throw new ArgumentNullException(nameof(query)); + } + + return Store.ListAsync(query, cancellationToken); + } } } \ No newline at end of file diff --git a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs index 6d32f488..9774e570 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs @@ -38,12 +38,6 @@ namespace OpenIddict.Core /// protected IOpenIddictTokenStore Store { get; } - /// - /// Gets the tokens as a queryable source, - /// if supported by the underlying store. - /// - public virtual IQueryable Tokens => Store.Tokens; - /// /// Creates a new token. /// @@ -157,6 +151,26 @@ namespace OpenIddict.Core return Store.FindBySubjectAsync(subject, cancellationToken); } + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public virtual Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) + { + if (query == null) + { + throw new ArgumentNullException(nameof(query)); + } + + return Store.GetAsync(query, cancellationToken); + } + /// /// Retrieves the optional authorization identifier associated with a token. /// @@ -356,6 +370,26 @@ namespace OpenIddict.Core return string.Equals(status, OpenIddictConstants.Statuses.Valid, StringComparison.OrdinalIgnoreCase); } + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public virtual Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) + { + if (query == null) + { + throw new ArgumentNullException(nameof(query)); + } + + return Store.ListAsync(query, cancellationToken); + } + /// /// Redeems a token. /// diff --git a/src/OpenIddict.Core/Stores/IOpenIddictApplicationStore.cs b/src/OpenIddict.Core/Stores/IOpenIddictApplicationStore.cs index 70f7b4e9..08965a07 100644 --- a/src/OpenIddict.Core/Stores/IOpenIddictApplicationStore.cs +++ b/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 /// The type of the Application entity. public interface IOpenIddictApplicationStore where TApplication : class { - /// - /// Gets the applications as a queryable source, if supported by the store. - /// - IQueryable Applications { get; } - /// /// Creates a new application. /// @@ -97,6 +93,18 @@ namespace OpenIddict.Core /// Task FindByRedirectUriAsync(string address, CancellationToken cancellationToken); + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + /// /// Retrieves the client identifier associated with an application. /// @@ -185,7 +193,19 @@ namespace OpenIddict.Core /// A that can be used to monitor the asynchronous operation, /// whose result returns the tokens associated with the application. /// - Task> GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken); + Task GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken); + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); /// /// Sets the client secret associated with an application. diff --git a/src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs b/src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs index bb5395e2..aaf3c41f 100644 --- a/src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs +++ b/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 /// The type of the Authorization entity. public interface IOpenIddictAuthorizationStore where TAuthorization : class { - /// - /// Gets the authorizations as a queryable source, if supported by the store. - /// - IQueryable Authorizations { get; } - /// /// Creates a new authorization. /// @@ -66,6 +61,18 @@ namespace OpenIddict.Core /// Task FindAsync(string subject, string client, CancellationToken cancellationToken); + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + /// /// Retrieves the unique identifier associated with an authorization. /// @@ -99,6 +106,18 @@ namespace OpenIddict.Core /// Task GetSubjectAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken); + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + /// /// Sets the status associated with an authorization. /// diff --git a/src/OpenIddict.Core/Stores/IOpenIddictScopeStore.cs b/src/OpenIddict.Core/Stores/IOpenIddictScopeStore.cs index 6c8eea2b..d1d59ebe 100644 --- a/src/OpenIddict.Core/Stores/IOpenIddictScopeStore.cs +++ b/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 where TScope : class { /// - /// Gets the scopes as a queryable source, if supported by the store. + /// Executes the specified query. /// - IQueryable Scopes { get; } + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs b/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs index 67491003..97512467 100644 --- a/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs +++ b/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs @@ -18,11 +18,6 @@ namespace OpenIddict.Core /// The type of the Token entity. public interface IOpenIddictTokenStore where TToken : class { - /// - /// Gets the tokens as a queryable source, if supported by the store. - /// - IQueryable Tokens { get; } - /// /// Creates a new token. /// @@ -95,6 +90,18 @@ namespace OpenIddict.Core /// Task FindBySubjectAsync(string subject, CancellationToken cancellationToken); + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + /// /// Retrieves the optional authorization identifier associated with a token. /// @@ -194,6 +201,18 @@ namespace OpenIddict.Core /// Task GetTokenTypeAsync([NotNull] TToken token, CancellationToken cancellationToken); + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + /// /// Sets the authorization associated with a token. /// diff --git a/src/OpenIddict.Core/Stores/OpenIddictApplicationStore.cs b/src/OpenIddict.Core/Stores/OpenIddictApplicationStore.cs new file mode 100644 index 00000000..80dcaf0f --- /dev/null +++ b/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 +{ + /// + /// Provides methods allowing to manage the applications stored in a database. + /// Note: this base class can only be used with the default OpenIddict entities. + /// + /// The type of the Application entity. + /// The type of the Authorization entity. + /// The type of the Token entity. + /// The type of the entity primary keys. + public abstract class OpenIddictApplicationStore : IOpenIddictApplicationStore + where TApplication : OpenIddictApplication, new() + where TAuthorization : OpenIddictAuthorization, new() + where TToken : OpenIddictToken, new() + where TKey : IEquatable + { + /// + /// Creates a new application. + /// + /// The application to create. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the application. + /// + public abstract Task CreateAsync([NotNull] TApplication application, CancellationToken cancellationToken); + + /// + /// Creates a new application. + /// + /// The application descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the application. + /// + public abstract Task CreateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken); + + /// + /// Removes an existing application. + /// + /// The application to delete. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public abstract Task DeleteAsync([NotNull] TApplication application, CancellationToken cancellationToken); + + /// + /// Retrieves an application using its unique identifier. + /// + /// The unique identifier associated with the application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the client application corresponding to the identifier. + /// + public virtual Task FindByIdAsync(string identifier, CancellationToken cancellationToken) + { + var key = ConvertIdentifierFromString(identifier); + + return GetAsync(applications => applications.Where(application => application.Id.Equals(key)), cancellationToken); + } + + /// + /// Retrieves an application using its client identifier. + /// + /// The client identifier associated with the application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the client application corresponding to the identifier. + /// + public virtual Task FindByClientIdAsync(string identifier, CancellationToken cancellationToken) + { + return GetAsync(applications => applications.Where(application => application.ClientId.Equals(identifier)), cancellationToken); + } + + /// + /// Retrieves all the applications associated with the specified post_logout_redirect_uri. + /// + /// The post_logout_redirect_uri associated with the applications. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result + /// returns the client applications corresponding to the specified post_logout_redirect_uri. + /// + public virtual Task FindByLogoutRedirectUriAsync(string address, CancellationToken cancellationToken) + { + return ListAsync(applications => applications.Where(application => application.LogoutRedirectUri == address), cancellationToken); + } + + /// + /// Retrieves all the applications associated with the specified redirect_uri. + /// + /// The redirect_uri associated with the applications. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result + /// returns the client applications corresponding to the specified redirect_uri. + /// + public virtual Task FindByRedirectUriAsync(string address, CancellationToken cancellationToken) + { + return ListAsync(applications => applications.Where(application => application.RedirectUri == address), cancellationToken); + } + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public abstract Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// Retrieves the client identifier associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the client identifier associated with the application. + /// + public virtual Task GetClientIdAsync([NotNull] TApplication application, CancellationToken cancellationToken) + { + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Task.FromResult(application.ClientId); + } + + /// + /// 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. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the client secret associated with the application. + /// + public virtual Task GetClientSecretAsync([NotNull] TApplication application, CancellationToken cancellationToken) + { + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Task.FromResult(application.ClientSecret); + } + + /// + /// Retrieves the client type associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the client type of the application (by default, "public"). + /// + public virtual Task GetClientTypeAsync([NotNull] TApplication application, CancellationToken cancellationToken) + { + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Task.FromResult(application.Type); + } + + /// + /// Retrieves the display name associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the display name associated with the application. + /// + public virtual Task GetDisplayNameAsync([NotNull] TApplication application, CancellationToken cancellationToken) + { + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Task.FromResult(application.DisplayName); + } + + /// + /// Retrieves the unique identifier associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the unique identifier associated with the application. + /// + public virtual Task GetIdAsync([NotNull] TApplication application, CancellationToken cancellationToken) + { + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Task.FromResult(ConvertIdentifierToString(application.Id)); + } + + /// + /// Retrieves the logout callback address associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the post_logout_redirect_uri associated with the application. + /// + public virtual Task GetLogoutRedirectUriAsync([NotNull] TApplication application, CancellationToken cancellationToken) + { + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Task.FromResult(application.LogoutRedirectUri); + } + + /// + /// Retrieves the callback address associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the redirect_uri associated with the application. + /// + public virtual Task GetRedirectUriAsync([NotNull] TApplication application, CancellationToken cancellationToken) + { + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Task.FromResult(application.RedirectUri); + } + + /// + /// Retrieves the token identifiers associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the tokens associated with the application. + /// + public virtual async Task GetTokensAsync([NotNull] TApplication application, CancellationToken cancellationToken) + { + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + var tokens = new List(); + + 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(); + } + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public abstract Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// 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. + /// + /// The application. + /// The client secret associated with the application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + 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); + } + + /// + /// Sets the client type associated with an application. + /// + /// The application. + /// The client type associated with the application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + 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); + } + + /// + /// Updates an existing application. + /// + /// The application to update. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public abstract Task UpdateAsync([NotNull] TApplication application, CancellationToken cancellationToken); + + /// + /// Converts the provided identifier to a strongly typed key object. + /// + /// The identifier to convert. + /// An instance of representing the provided identifier. + public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) + { + if (string.IsNullOrEmpty(identifier)) + { + return default(TKey); + } + + return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier); + } + + /// + /// Converts the provided identifier to its string representation. + /// + /// The identifier to convert. + /// A representation of the provided identifier. + public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) + { + if (Equals(identifier, default(TKey))) + { + return null; + } + + return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier); + } + } +} \ No newline at end of file diff --git a/src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs new file mode 100644 index 00000000..4d158503 --- /dev/null +++ b/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 +{ + /// + /// Provides methods allowing to manage the authorizations stored in a database. + /// Note: this base class can only be used with the default OpenIddict entities. + /// + /// The type of the Authorization entity. + /// The type of the Application entity. + /// The type of the Token entity. + /// The type of the entity primary keys. + public abstract class OpenIddictAuthorizationStore : IOpenIddictAuthorizationStore + where TAuthorization : OpenIddictAuthorization, new() + where TApplication : OpenIddictApplication, new() + where TToken : OpenIddictToken, new() + where TKey : IEquatable + { + /// + /// Creates a new authorization. + /// + /// The authorization to create. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the authorization. + /// + public abstract Task CreateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken); + + /// + /// Creates a new authorization. + /// + /// The authorization descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the authorization. + /// + public abstract Task CreateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken); + + /// + /// Retrieves an authorization using its associated subject/client. + /// + /// The subject associated with the authorization. + /// The client associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorization corresponding to the subject/client. + /// + public virtual Task 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); + } + + /// + /// Retrieves an authorization using its unique identifier. + /// + /// The unique identifier associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorization corresponding to the identifier. + /// + public virtual Task FindByIdAsync(string identifier, CancellationToken cancellationToken) + { + var key = ConvertIdentifierFromString(identifier); + + return GetAsync(authorizations => authorizations.Where(authorization => authorization.Id.Equals(key)), cancellationToken); + } + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public abstract Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// Retrieves the unique identifier associated with an authorization. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the unique identifier associated with the authorization. + /// + public virtual Task GetIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) + { + if (authorization == null) + { + throw new ArgumentNullException(nameof(authorization)); + } + + return Task.FromResult(ConvertIdentifierToString(authorization.Id)); + } + + /// + /// Retrieves the status associated with an authorization. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the status associated with the specified authorization. + /// + public virtual Task GetStatusAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) + { + return Task.FromResult(authorization.Status); + } + + /// + /// Retrieves the subject associated with an authorization. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the subject associated with the specified authorization. + /// + public virtual Task GetSubjectAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) + { + if (authorization == null) + { + throw new ArgumentNullException(nameof(authorization)); + } + + return Task.FromResult(authorization.Subject); + } + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public abstract Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// Sets the status associated with an authorization. + /// + /// The authorization. + /// The status associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public virtual Task SetStatusAsync([NotNull] TAuthorization authorization, [NotNull] string status, CancellationToken cancellationToken) + { + authorization.Status = status; + + return Task.CompletedTask; + } + + /// + /// Updates an existing authorization. + /// + /// The authorization to update. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public abstract Task UpdateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken); + + /// + /// Converts the provided identifier to a strongly typed key object. + /// + /// The identifier to convert. + /// An instance of representing the provided identifier. + public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) + { + if (string.IsNullOrEmpty(identifier)) + { + return default(TKey); + } + + return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier); + } + + /// + /// Converts the provided identifier to its string representation. + /// + /// The identifier to convert. + /// A representation of the provided identifier. + public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) + { + if (Equals(identifier, default(TKey))) + { + return null; + } + + return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier); + } + } +} \ No newline at end of file diff --git a/src/OpenIddict.Core/Stores/OpenIddictScopeStore.cs b/src/OpenIddict.Core/Stores/OpenIddictScopeStore.cs new file mode 100644 index 00000000..22c4520f --- /dev/null +++ b/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 +{ + /// + /// Provides methods allowing to manage the scopes stored in a database. + /// Note: this base class can only be used with the default OpenIddict entities. + /// + /// The type of the Scope entity. + /// The type of the entity primary keys. + public abstract class OpenIddictScopeStore : IOpenIddictScopeStore + where TScope : OpenIddictScope, new() + where TKey : IEquatable + { + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public abstract Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public abstract Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// Converts the provided identifier to a strongly typed key object. + /// + /// The identifier to convert. + /// An instance of representing the provided identifier. + public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) + { + if (string.IsNullOrEmpty(identifier)) + { + return default(TKey); + } + + return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier); + } + + /// + /// Converts the provided identifier to its string representation. + /// + /// The identifier to convert. + /// A representation of the provided identifier. + public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) + { + if (Equals(identifier, default(TKey))) + { + return null; + } + + return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier); + } + } +} \ No newline at end of file diff --git a/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs new file mode 100644 index 00000000..12a2cda0 --- /dev/null +++ b/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 +{ + /// + /// Provides methods allowing to manage the tokens stored in a database. + /// Note: this base class can only be used with the default OpenIddict entities. + /// + /// The type of the Token entity. + /// The type of the Application entity. + /// The type of the Authorization entity. + /// The type of the entity primary keys. + public abstract class OpenIddictTokenStore : IOpenIddictTokenStore + where TToken : OpenIddictToken, new() + where TApplication : OpenIddictApplication, new() + where TAuthorization : OpenIddictAuthorization, new() + where TKey : IEquatable + { + /// + /// Creates a new token. + /// + /// The token to create. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the token. + /// + public abstract Task CreateAsync([NotNull] TToken token, CancellationToken cancellationToken); + + /// + /// Creates a new token, which is associated with a particular subject. + /// + /// The token descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the token. + /// + public abstract Task CreateAsync([NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken); + + /// + /// Removes a token. + /// + /// The token to delete. + /// The that can be used to abort the operation. + /// A that can be used to monitor the asynchronous operation. + public abstract Task DeleteAsync([NotNull] TToken token, CancellationToken cancellationToken); + + /// + /// Retrieves the list of tokens corresponding to the specified authorization identifier. + /// + /// The authorization identifier associated with the tokens. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the tokens corresponding to the specified authorization. + /// + public virtual Task FindByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken) + { + var key = ConvertIdentifierFromString(identifier); + + return ListAsync(tokens => tokens.Where(token => token.Authorization.Id.Equals(key)), cancellationToken); + } + + /// + /// Retrieves the list of tokens corresponding to the specified hash. + /// + /// The hashed crypto-secure random identifier associated with the tokens. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the tokens corresponding to the specified hash. + /// + public virtual Task FindByHashAsync(string hash, CancellationToken cancellationToken) + { + return GetAsync(tokens => tokens.Where(token => token.Hash == hash), cancellationToken); + } + + /// + /// Retrieves an token using its unique identifier. + /// + /// The unique identifier associated with the token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the token corresponding to the unique identifier. + /// + public virtual Task FindByIdAsync(string identifier, CancellationToken cancellationToken) + { + var key = ConvertIdentifierFromString(identifier); + + return GetAsync(tokens => tokens.Where(token => token.Id.Equals(key)), cancellationToken); + } + + /// + /// Retrieves the list of tokens corresponding to the specified subject. + /// + /// The subject associated with the tokens. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the tokens corresponding to the specified subject. + /// + public virtual Task FindBySubjectAsync(string subject, CancellationToken cancellationToken) + { + return ListAsync(tokens => tokens.Where(token => token.Subject == subject), cancellationToken); + } + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public abstract Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// Retrieves the optional authorization identifier associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorization identifier associated with the token. + /// + public virtual async Task 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); + } + + /// + /// Retrieves the ciphertext associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the ciphertext associated with the specified token. + /// + public virtual Task GetCiphertextAsync([NotNull] TToken token, CancellationToken cancellationToken) + { + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Task.FromResult(token.Ciphertext); + } + + /// + /// Retrieves the creation date associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the creation date associated with the specified token. + /// + public virtual Task GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken) + { + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Task.FromResult(token.CreationDate); + } + + /// + /// Retrieves the expiration date associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the expiration date associated with the specified token. + /// + public virtual Task GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken) + { + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Task.FromResult(token.ExpirationDate); + } + + /// + /// Retrieves the hashed identifier associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the hashed identifier associated with the specified token. + /// + public virtual Task GetHashAsync([NotNull] TToken token, CancellationToken cancellationToken) + { + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Task.FromResult(token.Hash); + } + + /// + /// Retrieves the unique identifier associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the unique identifier associated with the token. + /// + public virtual Task GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken) + { + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Task.FromResult(ConvertIdentifierToString(token.Id)); + } + + /// + /// Retrieves the status associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the status associated with the specified token. + /// + public virtual Task GetStatusAsync([NotNull] TToken token, CancellationToken cancellationToken) + { + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Task.FromResult(token.Status); + } + + /// + /// Retrieves the subject associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the subject associated with the specified token. + /// + public virtual Task GetSubjectAsync([NotNull] TToken token, CancellationToken cancellationToken) + { + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Task.FromResult(token.Subject); + } + + /// + /// Retrieves the token type associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the token type associated with the specified token. + /// + public virtual Task GetTokenTypeAsync([NotNull] TToken token, CancellationToken cancellationToken) + { + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Task.FromResult(token.Type); + } + + /// + /// Executes the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public abstract Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken); + + /// + /// Sets the authorization associated with a token. + /// + /// The token. + /// The unique identifier associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public abstract Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken); + + /// + /// Sets the client application associated with a token. + /// + /// The token. + /// The unique identifier associated with the client application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public abstract Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken); + + /// + /// Sets the expiration date associated with a token. + /// + /// The token. + /// The date on which the token will no longer be considered valid. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public virtual Task SetExpirationDateAsync([NotNull] TToken token, + [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken) + { + token.ExpirationDate = date; + + return Task.CompletedTask; + } + + /// + /// Sets the status associated with a token. + /// + /// The token. + /// The status associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public virtual Task SetStatusAsync([NotNull] TToken token, [NotNull] string status, CancellationToken cancellationToken) + { + token.Status = status; + + return Task.CompletedTask; + } + + /// + /// Updates an existing token. + /// + /// The token to update. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + public abstract Task UpdateAsync([NotNull] TToken token, CancellationToken cancellationToken); + + /// + /// Converts the provided identifier to a strongly typed key object. + /// + /// The identifier to convert. + /// An instance of representing the provided identifier. + public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) + { + if (string.IsNullOrEmpty(identifier)) + { + return default(TKey); + } + + return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier); + } + + /// + /// Converts the provided identifier to its string representation. + /// + /// The identifier to convert. + /// A representation of the provided identifier. + public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) + { + if (Equals(identifier, default(TKey))) + { + return null; + } + + return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier); + } + } +} \ No newline at end of file diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs index a344f528..0ba5a373 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs +++ b/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 { /// /// Provides methods allowing to manage the applications stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Entity Framework database context. public class OpenIddictApplicationStore : OpenIddictApplicationStore /// Provides methods allowing to manage the applications stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Entity Framework database context. /// The type of the entity primary keys. @@ -45,13 +45,15 @@ namespace OpenIddict.EntityFrameworkCore /// /// Provides methods allowing to manage the applications stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Application entity. /// The type of the Authorization entity. /// The type of the Token entity. /// The type of the Entity Framework database context. /// The type of the entity primary keys. - public class OpenIddictApplicationStore : IOpenIddictApplicationStore + public class OpenIddictApplicationStore : + OpenIddictApplicationStore where TApplication : OpenIddictApplication, new() where TAuthorization : OpenIddictAuthorization, new() where TToken : OpenIddictToken, new() @@ -78,11 +80,6 @@ namespace OpenIddict.EntityFrameworkCore /// protected DbSet Applications => Context.Set(); - /// - /// Gets the applications as a queryable source, if supported by the store. - /// - IQueryable IOpenIddictApplicationStore.Applications => Applications; - /// /// Creates a new application. /// @@ -91,7 +88,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation, whose result returns the application. /// - public virtual async Task CreateAsync([NotNull] TApplication application, CancellationToken cancellationToken) + public override async Task CreateAsync([NotNull] TApplication application, CancellationToken cancellationToken) { if (application == null) { @@ -113,7 +110,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation, whose result returns the application. /// - public Task CreateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken) + public override Task CreateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken) { if (descriptor == null) { @@ -141,7 +138,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation. /// - 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 } /// - /// Retrieves an application using its unique identifier. - /// - /// The unique identifier associated with the application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the client application corresponding to the identifier. - /// - public virtual Task FindByIdAsync(string identifier, CancellationToken cancellationToken) - { - var key = ConvertIdentifierFromString(identifier); - - return Applications.SingleOrDefaultAsync(application => application.Id.Equals(key), cancellationToken); - } - - /// - /// Retrieves an application using its client identifier. - /// - /// The client identifier associated with the application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the client application corresponding to the identifier. - /// - public virtual Task FindByClientIdAsync(string identifier, CancellationToken cancellationToken) - { - return Applications.SingleOrDefaultAsync(application => application.ClientId.Equals(identifier), cancellationToken); - } - - /// - /// Retrieves all the applications associated with the specified post_logout_redirect_uri. - /// - /// The post_logout_redirect_uri associated with the applications. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, whose result - /// returns the client applications corresponding to the specified post_logout_redirect_uri. - /// - public virtual Task FindByLogoutRedirectUriAsync(string address, CancellationToken cancellationToken) - { - return Applications.Where(application => application.LogoutRedirectUri == address).ToArrayAsync(cancellationToken); - } - - /// - /// Retrieves all the applications associated with the specified redirect_uri. - /// - /// The redirect_uri associated with the applications. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, whose result - /// returns the client applications corresponding to the specified redirect_uri. - /// - public virtual Task FindByRedirectUriAsync(string address, CancellationToken cancellationToken) - { - return Applications.Where(application => application.RedirectUri == address).ToArrayAsync(cancellationToken); - } - - /// - /// Retrieves the client identifier associated with an application. - /// - /// The application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the client identifier associated with the application. - /// - public virtual Task GetClientIdAsync([NotNull] TApplication application, CancellationToken cancellationToken) - { - if (application == null) - { - throw new ArgumentNullException(nameof(application)); - } - - return Task.FromResult(application.ClientId); - } - - /// - /// 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. - /// - /// The application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the client secret associated with the application. - /// - public virtual Task GetClientSecretAsync([NotNull] TApplication application, CancellationToken cancellationToken) - { - if (application == null) - { - throw new ArgumentNullException(nameof(application)); - } - - return Task.FromResult(application.ClientSecret); - } - - /// - /// Retrieves the client type associated with an application. - /// - /// The application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the client type of the application (by default, "public"). - /// - public virtual Task GetClientTypeAsync([NotNull] TApplication application, CancellationToken cancellationToken) - { - if (application == null) - { - throw new ArgumentNullException(nameof(application)); - } - - return Task.FromResult(application.Type); - } - - /// - /// Retrieves the display name associated with an application. - /// - /// The application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the display name associated with the application. - /// - public virtual Task GetDisplayNameAsync([NotNull] TApplication application, CancellationToken cancellationToken) - { - if (application == null) - { - throw new ArgumentNullException(nameof(application)); - } - - return Task.FromResult(application.DisplayName); - } - - /// - /// Retrieves the unique identifier associated with an application. + /// Executes the specified query. /// - /// The application. + /// The result type. + /// The query to execute. /// The that can be used to abort the operation. /// /// A 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. /// - public virtual Task GetIdAsync([NotNull] TApplication application, CancellationToken cancellationToken) + public override Task GetAsync([NotNull] Func, IQueryable> 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); } /// - /// Retrieves the logout callback address associated with an application. + /// Executes the specified query. /// - /// The application. + /// The result type. + /// The query to execute. /// The that can be used to abort the operation. /// /// A that can be used to monitor the asynchronous operation, - /// whose result returns the post_logout_redirect_uri associated with the application. - /// - public virtual Task GetLogoutRedirectUriAsync([NotNull] TApplication application, CancellationToken cancellationToken) - { - if (application == null) - { - throw new ArgumentNullException(nameof(application)); - } - - return Task.FromResult(application.LogoutRedirectUri); - } - - /// - /// Retrieves the callback address associated with an application. - /// - /// The application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the redirect_uri associated with the application. - /// - public virtual Task GetRedirectUriAsync([NotNull] TApplication application, CancellationToken cancellationToken) - { - if (application == null) - { - throw new ArgumentNullException(nameof(application)); - } - - return Task.FromResult(application.RedirectUri); - } - - /// - /// Retrieves the token identifiers associated with an application. - /// - /// The application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the tokens associated with the application. - /// - public virtual async Task> 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(); - - foreach (var identifier in await query.ToArrayAsync()) - { - tokens.Add(ConvertIdentifierToString(identifier)); - } - - return tokens; - } - - /// - /// 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. - /// - /// The application. - /// The client secret associated with the application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation. + /// whose result returns all the elements returned when executing the specified query. /// - public virtual Task SetClientSecretAsync([NotNull] TApplication application, - [CanBeNull] string secret, CancellationToken cancellationToken) + public override Task ListAsync([NotNull] Func, IQueryable> 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); - } - - /// - /// Sets the client type associated with an application. - /// - /// The application. - /// The client type associated with the application. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation. - /// - 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); } /// @@ -440,7 +203,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation. /// - 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) { } } - - /// - /// Converts the provided identifier to a strongly typed key object. - /// - /// The identifier to convert. - /// An instance of representing the provided identifier. - public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) - { - if (string.IsNullOrEmpty(identifier)) - { - return default(TKey); - } - - return (TKey) TypeDescriptor.GetConverter(typeof(TKey)) - .ConvertFromInvariantString(identifier); - } - - /// - /// Converts the provided identifier to its string representation. - /// - /// The identifier to convert. - /// A representation of the provided identifier. - public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) - { - if (Equals(identifier, default(TKey))) - { - return null; - } - - return TypeDescriptor.GetConverter(typeof(TKey)) - .ConvertToInvariantString(identifier); - } } } \ No newline at end of file diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs index 9629bb62..6a1b7c83 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs +++ b/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 { /// /// Provides methods allowing to manage the authorizations stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Entity Framework database context. public class OpenIddictAuthorizationStore : OpenIddictAuthorizationStore /// Provides methods allowing to manage the authorizations stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Entity Framework database context. /// The type of the entity primary keys. @@ -45,13 +45,15 @@ namespace OpenIddict.EntityFrameworkCore /// /// Provides methods allowing to manage the authorizations stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Authorization entity. /// The type of the Application entity. /// The type of the Token entity. /// The type of the Entity Framework database context. /// The type of the entity primary keys. - public class OpenIddictAuthorizationStore : IOpenIddictAuthorizationStore + public class OpenIddictAuthorizationStore : + OpenIddictAuthorizationStore where TAuthorization : OpenIddictAuthorization, new() where TApplication : OpenIddictApplication, new() where TToken : OpenIddictToken, new() @@ -83,11 +85,6 @@ namespace OpenIddict.EntityFrameworkCore /// protected DbSet Authorizations => Context.Set(); - /// - /// Gets the authorizations as a queryable source, if supported by the store. - /// - IQueryable IOpenIddictAuthorizationStore.Authorizations => Authorizations; - /// /// Creates a new authorization. /// @@ -96,7 +93,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation, whose result returns the authorization. /// - public virtual async Task CreateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) + public override async Task CreateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) { if (authorization == null) { @@ -118,7 +115,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation, whose result returns the authorization. /// - public virtual async Task CreateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken) + public override async Task CreateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken) { if (descriptor == null) { @@ -149,108 +146,43 @@ namespace OpenIddict.EntityFrameworkCore } /// - /// Retrieves an authorization using its associated subject/client. - /// - /// The subject associated with the authorization. - /// The client associated with the authorization. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the authorization corresponding to the subject/client. - /// - public virtual Task 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(); - } - - /// - /// Retrieves an authorization using its unique identifier. + /// Executes the specified query. /// - /// The unique identifier associated with the authorization. + /// The result type. + /// The query to execute. /// The that can be used to abort the operation. /// /// A 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. /// - public virtual Task FindByIdAsync(string identifier, CancellationToken cancellationToken) + public override Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) { - var key = ConvertIdentifierFromString(identifier); - - return Authorizations.SingleOrDefaultAsync(authorization => authorization.Id.Equals(key), cancellationToken); - } - - /// - /// Retrieves the unique identifier associated with an authorization. - /// - /// The authorization. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the unique identifier associated with the authorization. - /// - public virtual Task 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)); - } - - /// - /// Retrieves the status associated with an authorization. - /// - /// The authorization. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the status associated with the specified authorization. - /// - public virtual Task GetStatusAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) - { - return Task.FromResult(authorization.Status); + return query.Invoke(Authorizations).SingleOrDefaultAsync(cancellationToken); } /// - /// Retrieves the subject associated with an authorization. + /// Executes the specified query. /// - /// The authorization. + /// The result type. + /// The query to execute. /// The that can be used to abort the operation. /// /// A 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. /// - public virtual Task GetSubjectAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) + public override Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) { - if (authorization == null) + if (query == null) { - throw new ArgumentNullException(nameof(authorization)); + throw new ArgumentNullException(nameof(query)); } - return Task.FromResult(authorization.Subject); - } - - /// - /// Sets the status associated with an authorization. - /// - /// The authorization. - /// The status associated with the authorization. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation. - /// - public virtual Task SetStatusAsync([NotNull] TAuthorization authorization, [NotNull] string status, CancellationToken cancellationToken) - { - authorization.Status = status; - - return Task.CompletedTask; + return query.Invoke(Authorizations).ToArrayAsync(cancellationToken); } /// @@ -261,7 +193,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation. /// - 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) { } } - - /// - /// Converts the provided identifier to a strongly typed key object. - /// - /// The identifier to convert. - /// An instance of representing the provided identifier. - public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) - { - if (string.IsNullOrEmpty(identifier)) - { - return default(TKey); - } - - return (TKey) TypeDescriptor.GetConverter(typeof(TKey)) - .ConvertFromInvariantString(identifier); - } - - /// - /// Converts the provided identifier to its string representation. - /// - /// The identifier to convert. - /// A representation of the provided identifier. - public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) - { - if (Equals(identifier, default(TKey))) - { - return null; - } - - return TypeDescriptor.GetConverter(typeof(TKey)) - .ConvertToInvariantString(identifier); - } } } \ No newline at end of file diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs index 7595cf72..ccd0b49f 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs +++ b/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 { /// /// Provides methods allowing to manage the scopes stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Entity Framework database context. public class OpenIddictScopeStore : OpenIddictScopeStore @@ -26,6 +27,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// Provides methods allowing to manage the scopes stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Entity Framework database context. /// The type of the entity primary keys. @@ -38,11 +40,12 @@ namespace OpenIddict.EntityFrameworkCore /// /// Provides methods allowing to manage the scopes stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Scope entity. /// The type of the Entity Framework database context. /// The type of the entity primary keys. - public class OpenIddictScopeStore : IOpenIddictScopeStore + public class OpenIddictScopeStore : Core.OpenIddictScopeStore where TScope : OpenIddictScope, new() where TContext : DbContext where TKey : IEquatable @@ -68,40 +71,43 @@ namespace OpenIddict.EntityFrameworkCore protected DbSet Scopes => Context.Set(); /// - /// Gets the scopes as a queryable source, if supported by the store. + /// Executes the specified query. /// - IQueryable IOpenIddictScopeStore.Scopes => Scopes; - - /// - /// Converts the provided identifier to a strongly typed key object. - /// - /// The identifier to convert. - /// An instance of representing the provided identifier. - public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the single element returned when executing the specified query. + /// + public override Task GetAsync([NotNull] Func, IQueryable> 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); } /// - /// Converts the provided identifier to its string representation. + /// Executes the specified query. /// - /// The identifier to convert. - /// A representation of the provided identifier. - public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + public override Task ListAsync([NotNull] Func, IQueryable> 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); } } } \ No newline at end of file diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs index 7dc2405c..39515293 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs +++ b/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 { /// /// Provides methods allowing to manage the tokens stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Entity Framework database context. public class OpenIddictTokenStore : OpenIddictTokenStore /// Provides methods allowing to manage the tokens stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Entity Framework database context. /// The type of the entity primary keys. @@ -44,13 +45,15 @@ namespace OpenIddict.EntityFrameworkCore /// /// Provides methods allowing to manage the tokens stored in a database. + /// Note: this class can only be used with the default OpenIddict entities. /// /// The type of the Token entity. /// The type of the Application entity. /// The type of the Authorization entity. /// The type of the Entity Framework database context. /// The type of the entity primary keys. - public class OpenIddictTokenStore : IOpenIddictTokenStore + public class OpenIddictTokenStore : + OpenIddictTokenStore where TToken : OpenIddictToken, new() where TApplication : OpenIddictApplication, new() where TAuthorization : OpenIddictAuthorization, new() @@ -87,11 +90,6 @@ namespace OpenIddict.EntityFrameworkCore /// protected DbSet Tokens => Context.Set(); - /// - /// Gets the tokens as a queryable source, if supported by the store. - /// - IQueryable IOpenIddictTokenStore.Tokens => Tokens; - /// /// Creates a new token. /// @@ -100,7 +98,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation, whose result returns the token. /// - public virtual async Task CreateAsync([NotNull] TToken token, CancellationToken cancellationToken) + public override async Task CreateAsync([NotNull] TToken token, CancellationToken cancellationToken) { if (token == null) { @@ -122,7 +120,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation, whose result returns the token. /// - public virtual async Task CreateAsync([NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken) + public override async Task CreateAsync([NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken) { if (descriptor == null) { @@ -176,7 +174,7 @@ namespace OpenIddict.EntityFrameworkCore /// The token to delete. /// The that can be used to abort the operation. /// A that can be used to monitor the asynchronous operation. - 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 } /// - /// Retrieves the list of tokens corresponding to the specified authorization identifier. - /// - /// The authorization identifier associated with the tokens. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the tokens corresponding to the specified authorization. - /// - public virtual Task FindByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken) - { - var key = ConvertIdentifierFromString(identifier); - - return Tokens.Where(token => token.Authorization.Id.Equals(key)).ToArrayAsync(cancellationToken); - } - - /// - /// Retrieves the list of tokens corresponding to the specified hash. - /// - /// The hashed crypto-secure random identifier associated with the tokens. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the tokens corresponding to the specified hash. - /// - public virtual Task FindByHashAsync(string hash, CancellationToken cancellationToken) - { - return Tokens.SingleOrDefaultAsync(token => token.Hash == hash, cancellationToken); - } - - /// - /// Retrieves an token using its unique identifier. - /// - /// The unique identifier associated with the token. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the token corresponding to the unique identifier. - /// - public virtual Task FindByIdAsync(string identifier, CancellationToken cancellationToken) - { - var key = ConvertIdentifierFromString(identifier); - - return Tokens.SingleOrDefaultAsync(token => token.Id.Equals(key), cancellationToken); - } - - /// - /// Retrieves the list of tokens corresponding to the specified subject. - /// - /// The subject associated with the tokens. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the tokens corresponding to the specified subject. - /// - public virtual Task FindBySubjectAsync(string subject, CancellationToken cancellationToken) - { - return Tokens.Where(token => token.Subject == subject).ToArrayAsync(); - } - - /// - /// Retrieves the optional authorization identifier associated with a token. - /// - /// The token. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the authorization identifier associated with the token. - /// - public virtual async Task 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); - } - - /// - /// Retrieves the ciphertext associated with a token. - /// - /// The token. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the ciphertext associated with the specified token. - /// - public virtual Task GetCiphertextAsync([NotNull] TToken token, CancellationToken cancellationToken) - { - if (token == null) - { - throw new ArgumentNullException(nameof(token)); - } - - return Task.FromResult(token.Ciphertext); - } - - /// - /// Retrieves the creation date associated with a token. + /// Executes the specified query. /// - /// The token. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the creation date associated with the specified token. - /// - public virtual Task GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken) - { - if (token == null) - { - throw new ArgumentNullException(nameof(token)); - } - - return Task.FromResult(token.CreationDate); - } - - /// - /// Retrieves the expiration date associated with a token. - /// - /// The token. + /// The result type. + /// The query to execute. /// The that can be used to abort the operation. /// /// A 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. /// - public virtual Task GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken) + public override Task GetAsync([NotNull] Func, IQueryable> 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); } /// - /// Retrieves the hashed identifier associated with a token. + /// Executes the specified query. /// - /// The token. + /// The result type. + /// The query to execute. /// The that can be used to abort the operation. /// /// A 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. /// - public virtual Task GetHashAsync([NotNull] TToken token, CancellationToken cancellationToken) + public override Task ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken) { - if (token == null) + if (query == null) { - throw new ArgumentNullException(nameof(token)); + throw new ArgumentNullException(nameof(query)); } - return Task.FromResult(token.Hash); - } - - /// - /// Retrieves the unique identifier associated with a token. - /// - /// The token. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the unique identifier associated with the token. - /// - public virtual Task GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken) - { - if (token == null) - { - throw new ArgumentNullException(nameof(token)); - } - - return Task.FromResult(ConvertIdentifierToString(token.Id)); - } - - /// - /// Retrieves the status associated with a token. - /// - /// The token. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the status associated with the specified token. - /// - public virtual Task GetStatusAsync([NotNull] TToken token, CancellationToken cancellationToken) - { - if (token == null) - { - throw new ArgumentNullException(nameof(token)); - } - - return Task.FromResult(token.Status); - } - - /// - /// Retrieves the subject associated with a token. - /// - /// The token. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the subject associated with the specified token. - /// - public virtual Task GetSubjectAsync([NotNull] TToken token, CancellationToken cancellationToken) - { - if (token == null) - { - throw new ArgumentNullException(nameof(token)); - } - - return Task.FromResult(token.Subject); - } - - /// - /// Retrieves the token type associated with a token. - /// - /// The token. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation, - /// whose result returns the token type associated with the specified token. - /// - public virtual Task 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); } /// @@ -437,7 +240,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation. /// - 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 /// /// A that can be used to monitor the asynchronous operation. /// - 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 } } - /// - /// Sets the expiration date associated with a token. - /// - /// The token. - /// The date on which the token will no longer be considered valid. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation. - /// - public virtual Task SetExpirationDateAsync([NotNull] TToken token, - [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken) - { - token.ExpirationDate = date; - - return Task.CompletedTask; - } - - /// - /// Sets the status associated with a token. - /// - /// The token. - /// The status associated with the authorization. - /// The that can be used to abort the operation. - /// - /// A that can be used to monitor the asynchronous operation. - /// - public virtual Task SetStatusAsync([NotNull] TToken token, [NotNull] string status, CancellationToken cancellationToken) - { - token.Status = status; - - return Task.CompletedTask; - } - /// /// Updates an existing token. /// @@ -555,7 +325,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation. /// - 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) { } } - - /// - /// Converts the provided identifier to a strongly typed key object. - /// - /// The identifier to convert. - /// An instance of representing the provided identifier. - public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) - { - if (string.IsNullOrEmpty(identifier)) - { - return default(TKey); - } - - return (TKey) TypeDescriptor.GetConverter(typeof(TKey)) - .ConvertFromInvariantString(identifier); - } - - /// - /// Converts the provided identifier to its string representation. - /// - /// The identifier to convert. - /// A representation of the provided identifier. - public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) - { - if (Equals(identifier, default(TKey))) - { - return null; - } - - return TypeDescriptor.GetConverter(typeof(TKey)) - .ConvertToInvariantString(identifier); - } } } \ No newline at end of file