74 changed files with 5806 additions and 3782 deletions
@ -0,0 +1,75 @@ |
|||
using System; |
|||
using System.Runtime.Serialization; |
|||
|
|||
namespace OpenIddict.Abstractions |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an OpenIddict exception.
|
|||
/// </summary>
|
|||
public class OpenIddictException : Exception |
|||
{ |
|||
/// <summary>
|
|||
/// Creates a new <see cref="OpenIddictException"/>.
|
|||
/// </summary>
|
|||
/// <param name="reason">The reason of the exception.</param>
|
|||
/// <param name="message">The exception message.</param>
|
|||
public OpenIddictException(string reason, string message) |
|||
: base(message) |
|||
{ |
|||
Reason = reason; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a new <see cref="OpenIddictException"/>.
|
|||
/// </summary>
|
|||
/// <param name="reason">The reason of the exception.</param>
|
|||
/// <param name="message">The exception message.</param>
|
|||
/// <param name="innerException">The inner exception.</param>
|
|||
public OpenIddictException(string reason, string message, Exception innerException) |
|||
: base(message, innerException) |
|||
{ |
|||
Reason = reason; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a new <see cref="OpenIddictException"/>.
|
|||
/// </summary>
|
|||
/// <param name="info">
|
|||
/// The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.
|
|||
/// </param>
|
|||
/// <param name="context">
|
|||
/// The <see cref="StreamingContext"/> that contains contextual information about the source or destination.
|
|||
/// </param>
|
|||
protected OpenIddictException(SerializationInfo info, StreamingContext context) |
|||
: base(info, context) |
|||
{ |
|||
Reason = info.GetString(nameof(Reason)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the reason that caused the exception to be thrown.
|
|||
/// </summary>
|
|||
public string Reason { get; } |
|||
|
|||
/// <summary>
|
|||
/// Serializes the members of this class.
|
|||
/// </summary>
|
|||
/// <param name="info">
|
|||
/// The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.
|
|||
/// </param>
|
|||
/// <param name="context">
|
|||
/// The <see cref="StreamingContext"/> that contains contextual information about the source or destination.
|
|||
/// </param>
|
|||
public override void GetObjectData(SerializationInfo info, StreamingContext context) |
|||
{ |
|||
if (info == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(info)); |
|||
} |
|||
|
|||
info.AddValue(nameof(Reason), Reason); |
|||
|
|||
base.GetObjectData(info, context); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,105 @@ |
|||
/* |
|||
* 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; |
|||
|
|||
namespace OpenIddict.EntityFramework.Models |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an OpenIddict application.
|
|||
/// </summary>
|
|||
public class OpenIddictApplication : OpenIddictApplication<string, OpenIddictAuthorization, OpenIddictToken> |
|||
{ |
|||
public OpenIddictApplication() |
|||
{ |
|||
// Generate a new string identifier.
|
|||
Id = Guid.NewGuid().ToString(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict application.
|
|||
/// </summary>
|
|||
public class OpenIddictApplication<TKey, TAuthorization, TToken> where TKey : IEquatable<TKey> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the list of the authorizations associated with this application.
|
|||
/// </summary>
|
|||
public virtual IList<TAuthorization> Authorizations { get; } = new List<TAuthorization>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the client identifier
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string ClientId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the client secret associated with the current application.
|
|||
/// Note: depending on the application manager used to create this instance,
|
|||
/// this property may be hashed or encrypted for security reasons.
|
|||
/// </summary>
|
|||
public virtual string ClientSecret { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the concurrency token.
|
|||
/// </summary>
|
|||
public virtual string ConcurrencyToken { get; set; } = Guid.NewGuid().ToString(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the consent type
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string ConsentType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the display name
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string DisplayName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unique identifier
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual TKey Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the permissions associated with the
|
|||
/// current application, serialized as a JSON array.
|
|||
/// </summary>
|
|||
public virtual string Permissions { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the logout callback URLs associated with
|
|||
/// the current application, serialized as a JSON array.
|
|||
/// </summary>
|
|||
public virtual string PostLogoutRedirectUris { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the additional properties serialized as a JSON object,
|
|||
/// or <c>null</c> if no bag was associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string Properties { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the callback URLs associated with the
|
|||
/// current application, serialized as a JSON array.
|
|||
/// </summary>
|
|||
public virtual string RedirectUris { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the list of the tokens associated with this application.
|
|||
/// </summary>
|
|||
public virtual IList<TToken> Tokens { get; } = new List<TToken>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the application type
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string Type { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
/* |
|||
* 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; |
|||
|
|||
namespace OpenIddict.EntityFramework.Models |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an OpenIddict authorization.
|
|||
/// </summary>
|
|||
public class OpenIddictAuthorization : OpenIddictAuthorization<string, OpenIddictApplication, OpenIddictToken> |
|||
{ |
|||
public OpenIddictAuthorization() |
|||
{ |
|||
// Generate a new string identifier.
|
|||
Id = Guid.NewGuid().ToString(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict authorization.
|
|||
/// </summary>
|
|||
public class OpenIddictAuthorization<TKey, TApplication, TToken> where TKey : IEquatable<TKey> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the application associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual TApplication Application { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the concurrency token.
|
|||
/// </summary>
|
|||
public virtual string ConcurrencyToken { get; set; } = Guid.NewGuid().ToString(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unique identifier
|
|||
/// associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual TKey Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the additional properties serialized as a JSON object,
|
|||
/// or <c>null</c> if no bag was associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual string Properties { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the scopes associated with the current
|
|||
/// authorization, serialized as a JSON array.
|
|||
/// </summary>
|
|||
public virtual string Scopes { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the status of the current authorization.
|
|||
/// </summary>
|
|||
public virtual string Status { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the subject associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual string Subject { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the list of tokens associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual IList<TToken> Tokens { get; } = new List<TToken>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type of the current authorization.
|
|||
/// </summary>
|
|||
public virtual string Type { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,97 @@ |
|||
/* |
|||
* 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; |
|||
|
|||
namespace OpenIddict.EntityFramework.Models |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an OpenIddict token.
|
|||
/// </summary>
|
|||
public class OpenIddictToken : OpenIddictToken<string, OpenIddictApplication, OpenIddictAuthorization> |
|||
{ |
|||
public OpenIddictToken() |
|||
{ |
|||
// Generate a new string identifier.
|
|||
Id = Guid.NewGuid().ToString(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict token.
|
|||
/// </summary>
|
|||
public class OpenIddictToken<TKey, TApplication, TAuthorization> where TKey : IEquatable<TKey> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the application associated with the current token.
|
|||
/// </summary>
|
|||
public virtual TApplication Application { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the authorization associated with the current token.
|
|||
/// </summary>
|
|||
public virtual TAuthorization Authorization { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the concurrency token.
|
|||
/// </summary>
|
|||
public virtual string ConcurrencyToken { get; set; } = Guid.NewGuid().ToString(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the date on which the token
|
|||
/// will start to be considered valid.
|
|||
/// </summary>
|
|||
public virtual DateTimeOffset? CreationDate { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the date on which the token
|
|||
/// will no longer be considered valid.
|
|||
/// </summary>
|
|||
public virtual DateTimeOffset? ExpirationDate { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unique identifier
|
|||
/// associated with the current token.
|
|||
/// </summary>
|
|||
public virtual TKey Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the payload of the current token, if applicable.
|
|||
/// Note: this property is only used for reference tokens
|
|||
/// and may be encrypted for security reasons.
|
|||
/// </summary>
|
|||
public virtual string Payload { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the additional properties serialized as a JSON object,
|
|||
/// or <c>null</c> if no bag was associated with the current token.
|
|||
/// </summary>
|
|||
public virtual string Properties { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the reference identifier associated
|
|||
/// with the current token, if applicable.
|
|||
/// Note: this property is only used for reference tokens
|
|||
/// and may be hashed or encrypted for security reasons.
|
|||
/// </summary>
|
|||
public virtual string ReferenceId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the status of the current token.
|
|||
/// </summary>
|
|||
public virtual string Status { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the subject associated with the current token.
|
|||
/// </summary>
|
|||
public virtual string Subject { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type of the current token.
|
|||
/// </summary>
|
|||
public virtual string Type { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
/* |
|||
* 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.Data.Entity; |
|||
using JetBrains.Annotations; |
|||
using OpenIddict.Core; |
|||
using OpenIddict.EntityFramework; |
|||
using OpenIddict.EntityFramework.Models; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes the necessary methods required to configure the OpenIddict Entity Framework 6.x services.
|
|||
/// </summary>
|
|||
public class OpenIddictEntityFrameworkBuilder |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of <see cref="OpenIddictEntityFrameworkBuilder"/>.
|
|||
/// </summary>
|
|||
/// <param name="services">The services collection.</param>
|
|||
public OpenIddictEntityFrameworkBuilder([NotNull] IServiceCollection services) |
|||
{ |
|||
if (services == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(services)); |
|||
} |
|||
|
|||
Services = services; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the services collection.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public IServiceCollection Services { get; } |
|||
|
|||
/// <summary>
|
|||
/// Amends the default OpenIddict Entity Framework 6.x configuration.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkBuilder Configure([NotNull] Action<OpenIddictEntityFrameworkOptions> configuration) |
|||
{ |
|||
if (configuration == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(configuration)); |
|||
} |
|||
|
|||
Services.Configure(configuration); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Configures the OpenIddict Entity Framework 6.x stores to use the specified database context type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TContext">The type of the <see cref="DbContext"/> used by OpenIddict.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkBuilder UseDbContext<TContext>() |
|||
where TContext : DbContext => UseDbContext(typeof(TContext)); |
|||
|
|||
/// <summary>
|
|||
/// Configures the OpenIddict Entity Framework 6.x stores to use the specified database context type.
|
|||
/// </summary>
|
|||
/// <param name="type">The type of the <see cref="DbContext"/> used by OpenIddict.</param>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkBuilder UseDbContext([NotNull] Type type) |
|||
{ |
|||
if (type == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(type)); |
|||
} |
|||
|
|||
if (!typeof(DbContext).IsAssignableFrom(type)) |
|||
{ |
|||
throw new ArgumentException("The specified type is invalid.", nameof(type)); |
|||
} |
|||
|
|||
return Configure(options => options.ContextType = type); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Configures OpenIddict to use the specified entities, derived
|
|||
/// from the default OpenIddict Entity Framework 6.x entities.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkBuilder ReplaceDefaultEntities<TApplication, TAuthorization, TScope, TToken, TKey>() |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new() |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new() |
|||
where TScope : OpenIddictScope<TKey>, new() |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new() |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
Services.Configure<OpenIddictCoreOptions>(options => |
|||
{ |
|||
options.DefaultApplicationType = typeof(TApplication); |
|||
options.DefaultAuthorizationType = typeof(TAuthorization); |
|||
options.DefaultScopeType = typeof(TScope); |
|||
options.DefaultTokenType = typeof(TToken); |
|||
}); |
|||
|
|||
return this; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
/* |
|||
* 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.Data.Entity; |
|||
|
|||
namespace OpenIddict.EntityFramework |
|||
{ |
|||
/// <summary>
|
|||
/// Provides various settings needed to configure
|
|||
/// the OpenIddict Entity Framework 6.x integration.
|
|||
/// </summary>
|
|||
public class OpenIddictEntityFrameworkOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the concrete type of the <see cref="DbContext"/> used by the
|
|||
/// OpenIddict Entity Framework 6.x stores. If this property is not populated,
|
|||
/// an exception is thrown at runtime when trying to use the stores.
|
|||
/// </summary>
|
|||
public Type ContextType { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\build\packages.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<Description>Relational entities for the Entity Framework Core stores.</Description> |
|||
<Authors>Kévin Chalet</Authors> |
|||
<PackageTags>aspnetcore;authentication;jwt;openidconnect;openiddict;security</PackageTags> |
|||
</PropertyGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,69 @@ |
|||
/* |
|||
* 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; |
|||
|
|||
namespace OpenIddict.EntityFrameworkCore.Models |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an OpenIddict scope.
|
|||
/// </summary>
|
|||
public class OpenIddictScope : OpenIddictScope<string> |
|||
{ |
|||
public OpenIddictScope() |
|||
{ |
|||
// Generate a new string identifier.
|
|||
Id = Guid.NewGuid().ToString(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict scope.
|
|||
/// </summary>
|
|||
public class OpenIddictScope<TKey> where TKey : IEquatable<TKey> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the concurrency token.
|
|||
/// </summary>
|
|||
public virtual string ConcurrencyToken { get; set; } = Guid.NewGuid().ToString(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the public description
|
|||
/// associated with the current scope.
|
|||
/// </summary>
|
|||
public virtual string Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the display name
|
|||
/// associated with the current scope.
|
|||
/// </summary>
|
|||
public virtual string DisplayName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unique identifier
|
|||
/// associated with the current scope.
|
|||
/// </summary>
|
|||
public virtual TKey Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unique name
|
|||
/// associated with the current scope.
|
|||
/// </summary>
|
|||
public virtual string Name { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the additional properties serialized as a JSON object,
|
|||
/// or <c>null</c> if no bag was associated with the current scope.
|
|||
/// </summary>
|
|||
public virtual string Properties { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the resources associated with the
|
|||
/// current scope, serialized as a JSON array.
|
|||
/// </summary>
|
|||
public virtual string Resources { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,123 @@ |
|||
/* |
|||
* 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 JetBrains.Annotations; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using OpenIddict.Core; |
|||
using OpenIddict.EntityFrameworkCore; |
|||
using OpenIddict.EntityFrameworkCore.Models; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes the necessary methods required to configure the OpenIddict Entity Framework Core services.
|
|||
/// </summary>
|
|||
public class OpenIddictEntityFrameworkCoreBuilder |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.
|
|||
/// </summary>
|
|||
/// <param name="services">The services collection.</param>
|
|||
public OpenIddictEntityFrameworkCoreBuilder([NotNull] IServiceCollection services) |
|||
{ |
|||
if (services == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(services)); |
|||
} |
|||
|
|||
Services = services; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the services collection.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public IServiceCollection Services { get; } |
|||
|
|||
/// <summary>
|
|||
/// Amends the default OpenIddict Entity Framework Core configuration.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkCoreBuilder Configure([NotNull] Action<OpenIddictEntityFrameworkCoreOptions> configuration) |
|||
{ |
|||
if (configuration == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(configuration)); |
|||
} |
|||
|
|||
Services.Configure(configuration); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Configures the OpenIddict Entity Framework Core stores to use the specified database context type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TContext">The type of the <see cref="DbContext"/> used by OpenIddict.</typeparam>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkCoreBuilder UseDbContext<TContext>() |
|||
where TContext : DbContext => UseDbContext(typeof(TContext)); |
|||
|
|||
/// <summary>
|
|||
/// Configures the OpenIddict Entity Framework Core stores to use the specified database context type.
|
|||
/// </summary>
|
|||
/// <param name="type">The type of the <see cref="DbContext"/> used by OpenIddict.</param>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkCoreBuilder UseDbContext([NotNull] Type type) |
|||
{ |
|||
if (type == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(type)); |
|||
} |
|||
|
|||
if (!typeof(DbContext).IsAssignableFrom(type)) |
|||
{ |
|||
throw new ArgumentException("The specified type is invalid.", nameof(type)); |
|||
} |
|||
|
|||
return Configure(options => options.ContextType = type); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Configures OpenIddict to use the default OpenIddict
|
|||
/// Entity Framework Core entities, with the specified key type.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkCoreBuilder ReplaceDefaultEntities<TKey>() |
|||
where TKey : IEquatable<TKey> |
|||
=> ReplaceDefaultEntities<OpenIddictApplication<TKey>, |
|||
OpenIddictAuthorization<TKey>, |
|||
OpenIddictScope<TKey>, |
|||
OpenIddictToken<TKey>, TKey>(); |
|||
|
|||
/// <summary>
|
|||
/// Configures OpenIddict to use the specified entities, derived
|
|||
/// from the default OpenIddict Entity Framework Core entities.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.</returns>
|
|||
public OpenIddictEntityFrameworkCoreBuilder ReplaceDefaultEntities<TApplication, TAuthorization, TScope, TToken, TKey>() |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new() |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new() |
|||
where TScope : OpenIddictScope<TKey>, new() |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new() |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
Services.Configure<OpenIddictCoreOptions>(options => |
|||
{ |
|||
options.DefaultApplicationType = typeof(TApplication); |
|||
options.DefaultAuthorizationType = typeof(TAuthorization); |
|||
options.DefaultScopeType = typeof(TScope); |
|||
options.DefaultTokenType = typeof(TToken); |
|||
}); |
|||
|
|||
return this; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
/* |
|||
* 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 Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace OpenIddict.EntityFrameworkCore |
|||
{ |
|||
/// <summary>
|
|||
/// Provides various settings needed to configure
|
|||
/// the OpenIddict Entity Framework Core integration.
|
|||
/// </summary>
|
|||
public class OpenIddictEntityFrameworkCoreOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the concrete type of the <see cref="DbContext"/> used by the
|
|||
/// OpenIddict Entity Framework Core stores. If this property is not populated,
|
|||
/// an exception is thrown at runtime when trying to use the stores.
|
|||
/// </summary>
|
|||
public Type ContextType { get; set; } |
|||
} |
|||
} |
|||
@ -1,25 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\build\packages.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<Description>Default base stores for OpenIddict.</Description> |
|||
<Authors>Kévin Chalet</Authors> |
|||
<PackageTags>aspnetcore;authentication;jwt;openidconnect;openiddict;security</PackageTags> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\OpenIddict.Abstractions\OpenIddict.Abstractions.csproj" /> |
|||
<ProjectReference Include="..\OpenIddict.Models\OpenIddict.Models.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="JetBrains.Annotations" Version="$(JetBrainsVersion)" PrivateAssets="All" /> |
|||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="$(AspNetCoreVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,832 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.ComponentModel; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace OpenIddict.Stores |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the applications stored in a database.
|
|||
/// Note: this base class can only be used with the default OpenIddict entities.
|
|||
/// </summary>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public abstract class OpenIddictApplicationStore<TApplication, TAuthorization, TToken, TKey> : IOpenIddictApplicationStore<TApplication> |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new() |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new() |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new() |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
protected OpenIddictApplicationStore([NotNull] IMemoryCache cache) |
|||
{ |
|||
if (cache == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(cache)); |
|||
} |
|||
|
|||
Cache = cache; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the memory cached associated with the current store.
|
|||
/// </summary>
|
|||
protected IMemoryCache Cache { get; } |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of applications that exist in the database.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of applications in the database.
|
|||
/// </returns>
|
|||
public virtual Task<long> CountAsync(CancellationToken cancellationToken) |
|||
{ |
|||
return CountAsync(applications => applications, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of applications that match the specified query.
|
|||
/// </summary>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of applications that match the specified query.
|
|||
/// </returns>
|
|||
public abstract Task<long> CountAsync<TResult>([NotNull] Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Creates a new application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to create.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task CreateAsync([NotNull] TApplication application, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes an existing application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to delete.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task DeleteAsync([NotNull] TApplication application, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client application corresponding to the identifier.
|
|||
/// </returns>
|
|||
public virtual Task<TApplication> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
IQueryable<TApplication> Query(IQueryable<TApplication> applications, TKey key) |
|||
=> from application in applications |
|||
where application.Id.Equals(key) |
|||
select application; |
|||
|
|||
return GetAsync((applications, key) => Query(applications, key), ConvertIdentifierFromString(identifier), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an application using its client identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The client identifier associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client application corresponding to the identifier.
|
|||
/// </returns>
|
|||
public virtual Task<TApplication> FindByClientIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
IQueryable<TApplication> Query(IQueryable<TApplication> applications, string id) |
|||
=> from application in applications |
|||
where application.ClientId == id |
|||
select application; |
|||
|
|||
return GetAsync((applications, id) => Query(applications, id), identifier, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the applications associated with the specified post_logout_redirect_uri.
|
|||
/// </summary>
|
|||
/// <param name="address">The post_logout_redirect_uri associated with the applications.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result
|
|||
/// returns the client applications corresponding to the specified post_logout_redirect_uri.
|
|||
/// </returns>
|
|||
public virtual async Task<ImmutableArray<TApplication>> FindByPostLogoutRedirectUriAsync([NotNull] string address, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(address)) |
|||
{ |
|||
throw new ArgumentException("The address cannot be null or empty.", nameof(address)); |
|||
} |
|||
|
|||
// To optimize the efficiency of the query a bit, only applications whose stringified
|
|||
// PostLogoutRedirectUris contains the specified URL are returned. Once the applications
|
|||
// are retrieved, a second pass is made to ensure only valid elements are returned.
|
|||
// Implementers that use this method in a hot path may want to override this method
|
|||
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
|
|||
IQueryable<TApplication> Query(IQueryable<TApplication> applications, string uri) |
|||
=> from application in applications |
|||
where application.PostLogoutRedirectUris.Contains(uri) |
|||
select application; |
|||
|
|||
var builder = ImmutableArray.CreateBuilder<TApplication>(); |
|||
|
|||
foreach (var application in await ListAsync((applications, uri) => Query(applications, uri), address, cancellationToken)) |
|||
{ |
|||
foreach (var uri in await GetPostLogoutRedirectUrisAsync(application, cancellationToken)) |
|||
{ |
|||
// Note: the post_logout_redirect_uri must be compared
|
|||
// using case-sensitive "Simple String Comparison".
|
|||
if (string.Equals(uri, address, StringComparison.Ordinal)) |
|||
{ |
|||
builder.Add(application); |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return builder.Count == builder.Capacity ? |
|||
builder.MoveToImmutable() : |
|||
builder.ToImmutable(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the applications associated with the specified redirect_uri.
|
|||
/// </summary>
|
|||
/// <param name="address">The redirect_uri associated with the applications.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result
|
|||
/// returns the client applications corresponding to the specified redirect_uri.
|
|||
/// </returns>
|
|||
public virtual async Task<ImmutableArray<TApplication>> FindByRedirectUriAsync([NotNull] string address, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(address)) |
|||
{ |
|||
throw new ArgumentException("The address cannot be null or empty.", nameof(address)); |
|||
} |
|||
|
|||
// To optimize the efficiency of the query a bit, only applications whose stringified
|
|||
// RedirectUris property contains the specified URL are returned. Once the applications
|
|||
// are retrieved, a second pass is made to ensure only valid elements are returned.
|
|||
// Implementers that use this method in a hot path may want to override this method
|
|||
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
|
|||
IQueryable<TApplication> Query(IQueryable<TApplication> applications, string uri) |
|||
=> from application in applications |
|||
where application.RedirectUris.Contains(uri) |
|||
select application; |
|||
|
|||
var builder = ImmutableArray.CreateBuilder<TApplication>(); |
|||
|
|||
foreach (var application in await ListAsync((applications, uri) => Query(applications, uri), address, cancellationToken)) |
|||
{ |
|||
foreach (var uri in await GetRedirectUrisAsync(application, cancellationToken)) |
|||
{ |
|||
// Note: the redirect_uri must be compared using case-sensitive "Simple String Comparison".
|
|||
// See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest for more information.
|
|||
if (string.Equals(uri, address, StringComparison.Ordinal)) |
|||
{ |
|||
builder.Add(application); |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return builder.Count == builder.Capacity ? |
|||
builder.MoveToImmutable() : |
|||
builder.ToImmutable(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns the first element.
|
|||
/// </summary>
|
|||
/// <typeparam name="TState">The state type.</typeparam>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="state">The optional state.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the first element returned when executing the query.
|
|||
/// </returns>
|
|||
public abstract Task<TResult> GetAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the client identifier associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client identifier associated with the application.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetClientIdAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return new ValueTask<string>(application.ClientId); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the client secret associated with an application.
|
|||
/// Note: depending on the manager used to create the application,
|
|||
/// the client secret may be hashed for security reasons.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client secret associated with the application.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetClientSecretAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return new ValueTask<string>(application.ClientSecret); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the client type associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the client type of the application (by default, "public").
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetClientTypeAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return new ValueTask<string>(application.Type); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the consent type associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the consent type of the application (by default, "explicit").
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetConsentTypeAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return new ValueTask<string>(application.ConsentType); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the display name associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the display name associated with the application.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetDisplayNameAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return new ValueTask<string>(application.DisplayName); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the unique identifier associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the unique identifier associated with the application.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetIdAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
return new ValueTask<string>(ConvertIdentifierToString(application.Id)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the permissions associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the permissions associated with the application.
|
|||
/// </returns>
|
|||
public virtual ValueTask<ImmutableArray<string>> GetPermissionsAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(application.Permissions)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<string>>(ImmutableArray.Create<string>()); |
|||
} |
|||
|
|||
// Note: parsing the stringified permissions is an expensive operation.
|
|||
// To mitigate that, the resulting array is stored in the memory cache.
|
|||
var key = string.Concat("0347e0aa-3a26-410a-97e8-a83bdeb21a1f", "\x1e", application.Permissions); |
|||
var permissions = Cache.GetOrCreate(key, entry => |
|||
{ |
|||
entry.SetPriority(CacheItemPriority.High) |
|||
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); |
|||
|
|||
return JArray.Parse(application.Permissions) |
|||
.Select(element => (string) element) |
|||
.ToImmutableArray(); |
|||
}); |
|||
|
|||
return new ValueTask<ImmutableArray<string>>(permissions); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the logout callback addresses associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the post_logout_redirect_uri associated with the application.
|
|||
/// </returns>
|
|||
public virtual ValueTask<ImmutableArray<string>> GetPostLogoutRedirectUrisAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(application.PostLogoutRedirectUris)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<string>>(ImmutableArray.Create<string>()); |
|||
} |
|||
|
|||
// Note: parsing the stringified addresses is an expensive operation.
|
|||
// To mitigate that, the resulting array is stored in the memory cache.
|
|||
var key = string.Concat("fb14dfb9-9216-4b77-bfa9-7e85f8201ff4", "\x1e", application.PostLogoutRedirectUris); |
|||
var addresses = Cache.GetOrCreate(key, entry => |
|||
{ |
|||
entry.SetPriority(CacheItemPriority.High) |
|||
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); |
|||
|
|||
return JArray.Parse(application.PostLogoutRedirectUris) |
|||
.Select(element => (string) element) |
|||
.ToImmutableArray(); |
|||
}); |
|||
|
|||
return new ValueTask<ImmutableArray<string>>(addresses); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the additional properties associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the additional properties associated with the application.
|
|||
/// </returns>
|
|||
public virtual ValueTask<JObject> GetPropertiesAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(application.Properties)) |
|||
{ |
|||
return new ValueTask<JObject>(new JObject()); |
|||
} |
|||
|
|||
return new ValueTask<JObject>(JObject.Parse(application.Properties)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the callback addresses associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the redirect_uri associated with the application.
|
|||
/// </returns>
|
|||
public virtual ValueTask<ImmutableArray<string>> GetRedirectUrisAsync([NotNull] TApplication application, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(application.RedirectUris)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<string>>(ImmutableArray.Create<string>()); |
|||
} |
|||
|
|||
// Note: parsing the stringified addresses is an expensive operation.
|
|||
// To mitigate that, the resulting array is stored in the memory cache.
|
|||
var key = string.Concat("851d6f08-2ee0-4452-bbe5-ab864611ecaa", "\x1e", application.RedirectUris); |
|||
var addresses = Cache.GetOrCreate(key, entry => |
|||
{ |
|||
entry.SetPriority(CacheItemPriority.High) |
|||
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); |
|||
|
|||
return JArray.Parse(application.RedirectUris) |
|||
.Select(element => (string) element) |
|||
.ToImmutableArray(); |
|||
}); |
|||
|
|||
return new ValueTask<ImmutableArray<string>>(addresses); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Instantiates a new application.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the instantiated application, that can be persisted in the database.
|
|||
/// </returns>
|
|||
public virtual ValueTask<TApplication> InstantiateAsync(CancellationToken cancellationToken) |
|||
=> new ValueTask<TApplication>(new TApplication()); |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns all the corresponding elements.
|
|||
/// </summary>
|
|||
/// <param name="count">The number of results to return.</param>
|
|||
/// <param name="offset">The number of results to skip.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the elements returned when executing the specified query.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TApplication>> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken) |
|||
{ |
|||
IQueryable<TApplication> Query(IQueryable<TApplication> applications, int? skip, int? take) |
|||
{ |
|||
var query = applications.OrderBy(application => application.Id).AsQueryable(); |
|||
|
|||
if (skip.HasValue) |
|||
{ |
|||
query = query.Skip(skip.Value); |
|||
} |
|||
|
|||
if (take.HasValue) |
|||
{ |
|||
query = query.Take(take.Value); |
|||
} |
|||
|
|||
return query; |
|||
} |
|||
|
|||
return ListAsync((applications, state) => Query(applications, state.offset, state.count), (offset, count), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns all the corresponding elements.
|
|||
/// </summary>
|
|||
/// <typeparam name="TState">The state type.</typeparam>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="state">The optional state.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the elements returned when executing the specified query.
|
|||
/// </returns>
|
|||
public abstract Task<ImmutableArray<TResult>> ListAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Sets the client identifier associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="identifier">The client identifier associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetClientIdAsync([NotNull] TApplication application, |
|||
[CanBeNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
application.ClientId = identifier; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the client secret associated with an application.
|
|||
/// Note: depending on the manager used to create the application,
|
|||
/// the client secret may be hashed for security reasons.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="secret">The client secret associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetClientSecretAsync([NotNull] TApplication application, |
|||
[CanBeNull] string secret, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
application.ClientSecret = secret; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the client type associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="type">The client type associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetClientTypeAsync([NotNull] TApplication application, |
|||
[CanBeNull] string type, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
application.Type = type; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the consent type associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="type">The consent type associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetConsentTypeAsync([NotNull] TApplication application, |
|||
[CanBeNull] string type, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
application.ConsentType = type; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the display name associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="name">The display name associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetDisplayNameAsync([NotNull] TApplication application, |
|||
[CanBeNull] string name, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
application.DisplayName = name; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the permissions associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="permissions">The permissions associated with the application </param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetPermissionsAsync([NotNull] TApplication application, ImmutableArray<string> permissions, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (permissions.IsDefaultOrEmpty) |
|||
{ |
|||
application.Permissions = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
application.Permissions = new JArray(permissions.ToArray()).ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the logout callback addresses associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="addresses">The logout callback addresses associated with the application </param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetPostLogoutRedirectUrisAsync([NotNull] TApplication application, |
|||
ImmutableArray<string> addresses, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (addresses.IsDefaultOrEmpty) |
|||
{ |
|||
application.PostLogoutRedirectUris = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
application.PostLogoutRedirectUris = new JArray(addresses.ToArray()).ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the additional properties associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="properties">The additional properties associated with the application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetPropertiesAsync([NotNull] TApplication application, [CanBeNull] JObject properties, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (properties == null) |
|||
{ |
|||
application.Properties = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
application.Properties = properties.ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the callback addresses associated with an application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application.</param>
|
|||
/// <param name="addresses">The callback addresses associated with the application </param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetRedirectUrisAsync([NotNull] TApplication application, |
|||
ImmutableArray<string> addresses, CancellationToken cancellationToken) |
|||
{ |
|||
if (application == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(application)); |
|||
} |
|||
|
|||
if (addresses.IsDefaultOrEmpty) |
|||
{ |
|||
application.RedirectUris = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
application.RedirectUris = new JArray(addresses.ToArray()).ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Updates an existing application.
|
|||
/// </summary>
|
|||
/// <param name="application">The application to update.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task UpdateAsync([NotNull] TApplication application, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Converts the provided identifier to a strongly typed key object.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The identifier to convert.</param>
|
|||
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
|
|||
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the provided identifier to its string representation.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The identifier to convert.</param>
|
|||
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
|
|||
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) |
|||
{ |
|||
if (Equals(identifier, default(TKey))) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier); |
|||
} |
|||
} |
|||
} |
|||
@ -1,694 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.ComponentModel; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace OpenIddict.Stores |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the authorizations stored in a database.
|
|||
/// Note: this base class can only be used with the default OpenIddict entities.
|
|||
/// </summary>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public abstract class OpenIddictAuthorizationStore<TAuthorization, TApplication, TToken, TKey> : IOpenIddictAuthorizationStore<TAuthorization> |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new() |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new() |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new() |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
protected OpenIddictAuthorizationStore([NotNull] IMemoryCache cache) |
|||
{ |
|||
if (cache == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(cache)); |
|||
} |
|||
|
|||
Cache = cache; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the memory cached associated with the current store.
|
|||
/// </summary>
|
|||
protected IMemoryCache Cache { get; } |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of authorizations that exist in the database.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of authorizations in the database.
|
|||
/// </returns>
|
|||
public virtual Task<long> CountAsync(CancellationToken cancellationToken) |
|||
{ |
|||
return CountAsync(authorizations => authorizations, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of authorizations that match the specified query.
|
|||
/// </summary>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of authorizations that match the specified query.
|
|||
/// </returns>
|
|||
public abstract Task<long> CountAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Creates a new authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization to create.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task CreateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes an existing authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization to delete.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task DeleteAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations corresponding to the specified
|
|||
/// subject and associated with the application identifier.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the subject/client.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, TKey key, string principal) |
|||
=> from authorization in authorizations |
|||
where authorization.Application != null && |
|||
authorization.Application.Id.Equals(key) && |
|||
authorization.Subject == principal |
|||
select authorization; |
|||
|
|||
return ListAsync( |
|||
(authorizations, state) => Query(authorizations, state.key, state.principal), |
|||
(key: ConvertIdentifierFromString(client), principal: subject), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the criteria.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(status)) |
|||
{ |
|||
throw new ArgumentException("The status cannot be null or empty.", nameof(status)); |
|||
} |
|||
|
|||
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, TKey key, string principal, string state) |
|||
=> from authorization in authorizations |
|||
where authorization.Application != null && |
|||
authorization.Application.Id.Equals(key) && |
|||
authorization.Subject == principal && |
|||
authorization.Status == state |
|||
select authorization; |
|||
|
|||
return ListAsync( |
|||
(authorizations, state) => Query(authorizations, state.key, state.principal, state.state), |
|||
(key: ConvertIdentifierFromString(client), principal: subject, state: status), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="type">The authorization type.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the criteria.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TAuthorization>> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, [NotNull] string type, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(client)) |
|||
{ |
|||
throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(status)) |
|||
{ |
|||
throw new ArgumentException("The status cannot be null or empty.", nameof(status)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(type)) |
|||
{ |
|||
throw new ArgumentException("The type cannot be null or empty.", nameof(type)); |
|||
} |
|||
|
|||
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, |
|||
TKey key, string principal, string state, string kind) |
|||
=> from authorization in authorizations |
|||
where authorization.Application != null && |
|||
authorization.Application.Id.Equals(key) && |
|||
authorization.Subject == principal && |
|||
authorization.Status == state && |
|||
authorization.Type == kind |
|||
select authorization; |
|||
|
|||
return ListAsync( |
|||
(authorizations, state) => Query(authorizations, state.key, state.principal, state.state, state.kind), |
|||
(key: ConvertIdentifierFromString(client), principal: subject, state: status, kind: type), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an authorization using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorization corresponding to the identifier.
|
|||
/// </returns>
|
|||
public virtual Task<TAuthorization> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, TKey key) |
|||
=> from authorization in authorizations |
|||
where authorization.Id.Equals(key) |
|||
select authorization; |
|||
|
|||
return GetAsync((authorizations, key) => Query(authorizations, key), ConvertIdentifierFromString(identifier), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the authorizations corresponding to the specified subject.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorizations corresponding to the specified subject.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TAuthorization>> FindBySubjectAsync( |
|||
[NotNull] string subject, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, string principal) |
|||
=> from authorization in authorizations |
|||
where authorization.Subject == principal |
|||
select authorization; |
|||
|
|||
return ListAsync((authorizations, principal) => Query(authorizations, principal), subject, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the optional application identifier associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the application identifier associated with the authorization.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (authorization.Application != null) |
|||
{ |
|||
return new ValueTask<string>(ConvertIdentifierToString(authorization.Application.Id)); |
|||
} |
|||
|
|||
async Task<string> RetrieveApplicationIdAsync() |
|||
{ |
|||
IQueryable<TKey> Query(IQueryable<TAuthorization> authorizations, TKey key) |
|||
=> from element in authorizations |
|||
where element.Id.Equals(key) && |
|||
element.Application != null |
|||
select element.Application.Id; |
|||
|
|||
return ConvertIdentifierToString(await GetAsync( |
|||
(authorizations, key) => Query(authorizations, key), authorization.Id, cancellationToken)); |
|||
} |
|||
|
|||
return new ValueTask<string>(RetrieveApplicationIdAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns the first element.
|
|||
/// </summary>
|
|||
/// <typeparam name="TState">The state type.</typeparam>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="state">The optional state.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the first element returned when executing the query.
|
|||
/// </returns>
|
|||
public abstract Task<TResult> GetAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the unique identifier associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the unique identifier associated with the authorization.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
return new ValueTask<string>(ConvertIdentifierToString(authorization.Id)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the additional properties associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the additional properties associated with the authorization.
|
|||
/// </returns>
|
|||
public virtual ValueTask<JObject> GetPropertiesAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(authorization.Properties)) |
|||
{ |
|||
return new ValueTask<JObject>(new JObject()); |
|||
} |
|||
|
|||
return new ValueTask<JObject>(JObject.Parse(authorization.Properties)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the scopes associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scopes associated with the specified authorization.
|
|||
/// </returns>
|
|||
public virtual ValueTask<ImmutableArray<string>> GetScopesAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(authorization.Scopes)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<string>>(ImmutableArray.Create<string>()); |
|||
} |
|||
|
|||
return new ValueTask<ImmutableArray<string>>(JArray.Parse(authorization.Scopes).Select(element => (string) element).ToImmutableArray()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the status associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the status associated with the specified authorization.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetStatusAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
return new ValueTask<string>(authorization.Status); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the subject associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the subject associated with the specified authorization.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetSubjectAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
return new ValueTask<string>(authorization.Subject); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the type associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the type associated with the specified authorization.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetTypeAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
return new ValueTask<string>(authorization.Type); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Instantiates a new authorization.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the instantiated authorization, that can be persisted in the database.
|
|||
/// </returns>
|
|||
public virtual ValueTask<TAuthorization> InstantiateAsync(CancellationToken cancellationToken) |
|||
=> new ValueTask<TAuthorization>(new TAuthorization()); |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns all the corresponding elements.
|
|||
/// </summary>
|
|||
/// <param name="count">The number of results to return.</param>
|
|||
/// <param name="offset">The number of results to skip.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the elements returned when executing the specified query.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TAuthorization>> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken) |
|||
{ |
|||
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, int? skip, int? take) |
|||
{ |
|||
var query = authorizations.OrderBy(authorization => authorization.Id).AsQueryable(); |
|||
|
|||
if (skip.HasValue) |
|||
{ |
|||
query = query.Skip(skip.Value); |
|||
} |
|||
|
|||
if (take.HasValue) |
|||
{ |
|||
query = query.Take(take.Value); |
|||
} |
|||
|
|||
return query; |
|||
} |
|||
|
|||
return ListAsync((authorizations, state) => Query(authorizations, state.offset, state.count), (offset, count), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns all the corresponding elements.
|
|||
/// </summary>
|
|||
/// <typeparam name="TState">The state type.</typeparam>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="state">The optional state.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the elements returned when executing the specified query.
|
|||
/// </returns>
|
|||
public abstract Task<ImmutableArray<TResult>> ListAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes the ad-hoc authorizations that are marked as invalid or have no valid token attached.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task PruneAsync(CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Sets the application identifier associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="identifier">The unique identifier associated with the client application.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task SetApplicationIdAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Sets the additional properties associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="properties">The additional properties associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetPropertiesAsync([NotNull] TAuthorization authorization, [CanBeNull] JObject properties, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (properties == null) |
|||
{ |
|||
authorization.Properties = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
authorization.Properties = properties.ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the scopes associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="scopes">The scopes associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetScopesAsync([NotNull] TAuthorization authorization, |
|||
ImmutableArray<string> scopes, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (scopes.IsDefaultOrEmpty) |
|||
{ |
|||
authorization.Scopes = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
authorization.Scopes = new JArray(scopes.ToArray()).ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the status associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="status">The status associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetStatusAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] string status, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
authorization.Status = status; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the subject associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetSubjectAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] string subject, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
authorization.Subject = subject; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the type associated with an authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization.</param>
|
|||
/// <param name="type">The type associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetTypeAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] string type, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
authorization.Type = type; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Updates an existing authorization.
|
|||
/// </summary>
|
|||
/// <param name="authorization">The authorization to update.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task UpdateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Converts the provided identifier to a strongly typed key object.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The identifier to convert.</param>
|
|||
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
|
|||
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the provided identifier to its string representation.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The identifier to convert.</param>
|
|||
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
|
|||
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) |
|||
{ |
|||
if (Equals(identifier, default(TKey))) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier); |
|||
} |
|||
} |
|||
} |
|||
@ -1,577 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.ComponentModel; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace OpenIddict.Stores |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the scopes stored in a database.
|
|||
/// Note: this base class can only be used with the default OpenIddict entities.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public abstract class OpenIddictScopeStore<TScope, TKey> : IOpenIddictScopeStore<TScope> |
|||
where TScope : OpenIddictScope<TKey>, new() |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
protected OpenIddictScopeStore([NotNull] IMemoryCache cache) |
|||
{ |
|||
if (cache == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(cache)); |
|||
} |
|||
|
|||
Cache = cache; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the memory cached associated with the current store.
|
|||
/// </summary>
|
|||
protected IMemoryCache Cache { get; } |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of scopes that exist in the database.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of scopes in the database.
|
|||
/// </returns>
|
|||
public virtual Task<long> CountAsync(CancellationToken cancellationToken) |
|||
{ |
|||
return CountAsync(scopes => scopes, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of scopes that match the specified query.
|
|||
/// </summary>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of scopes that match the specified query.
|
|||
/// </returns>
|
|||
public abstract Task<long> CountAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Creates a new scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope to create.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task CreateAsync([NotNull] TScope scope, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes an existing scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope to delete.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task DeleteAsync([NotNull] TScope scope, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a scope using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scope corresponding to the identifier.
|
|||
/// </returns>
|
|||
public virtual Task<TScope> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
IQueryable<TScope> Query(IQueryable<TScope> scopes, TKey key) |
|||
=> from scope in scopes |
|||
where scope.Id.Equals(key) |
|||
select scope; |
|||
|
|||
return GetAsync((scopes, key) => Query(scopes, key), ConvertIdentifierFromString(identifier), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a scope using its name.
|
|||
/// </summary>
|
|||
/// <param name="name">The name associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scope corresponding to the specified name.
|
|||
/// </returns>
|
|||
public virtual Task<TScope> FindByNameAsync([NotNull] string name, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(name)) |
|||
{ |
|||
throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); |
|||
} |
|||
|
|||
IQueryable<TScope> Query(IQueryable<TScope> scopes, string state) |
|||
=> from scope in scopes |
|||
where scope.Name == state |
|||
select scope; |
|||
|
|||
return GetAsync((scopes, state) => Query(scopes, state), name, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a list of scopes using their name.
|
|||
/// </summary>
|
|||
/// <param name="names">The names associated with the scopes.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scopes corresponding to the specified names.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TScope>> FindByNamesAsync( |
|||
ImmutableArray<string> names, CancellationToken cancellationToken) |
|||
{ |
|||
if (names.Any(name => string.IsNullOrEmpty(name))) |
|||
{ |
|||
throw new ArgumentException("Scope names cannot be null or empty.", nameof(names)); |
|||
} |
|||
|
|||
IQueryable<TScope> Query(IQueryable<TScope> scopes, string[] values) |
|||
=> from scope in scopes |
|||
where values.Contains(scope.Name) |
|||
select scope; |
|||
|
|||
return ListAsync((scopes, values) => Query(scopes, values), names.ToArray(), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves all the scopes that contain the specified resource.
|
|||
/// </summary>
|
|||
/// <param name="resource">The resource associated with the scopes.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scopes associated with the specified resource.
|
|||
/// </returns>
|
|||
public virtual async Task<ImmutableArray<TScope>> FindByResourceAsync( |
|||
[NotNull] string resource, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(resource)) |
|||
{ |
|||
throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); |
|||
} |
|||
|
|||
// To optimize the efficiency of the query a bit, only scopes whose stringified
|
|||
// Resources column contains the specified resource are returned. Once the scopes
|
|||
// are retrieved, a second pass is made to ensure only valid elements are returned.
|
|||
// Implementers that use this method in a hot path may want to override this method
|
|||
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
|
|||
IQueryable<TScope> Query(IQueryable<TScope> scopes, string state) |
|||
=> from scope in scopes |
|||
where scope.Resources.Contains(state) |
|||
select scope; |
|||
|
|||
var builder = ImmutableArray.CreateBuilder<TScope>(); |
|||
|
|||
foreach (var application in await ListAsync((applications, state) => Query(applications, state), resource, cancellationToken)) |
|||
{ |
|||
var resources = await GetResourcesAsync(application, cancellationToken); |
|||
if (resources.Contains(resource, StringComparer.OrdinalIgnoreCase)) |
|||
{ |
|||
builder.Add(application); |
|||
} |
|||
} |
|||
|
|||
return builder.ToImmutable(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns the first element.
|
|||
/// </summary>
|
|||
/// <typeparam name="TState">The state type.</typeparam>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="state">The optional state.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the first element returned when executing the query.
|
|||
/// </returns>
|
|||
public abstract Task<TResult> GetAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TScope>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the description associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the description associated with the specified scope.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetDescriptionAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
return new ValueTask<string>(scope.Description); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the display name associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the display name associated with the scope.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetDisplayNameAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
return new ValueTask<string>(scope.DisplayName); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the unique identifier associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the unique identifier associated with the scope.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetIdAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
return new ValueTask<string>(ConvertIdentifierToString(scope.Id)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the name associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the name associated with the specified scope.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetNameAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
return new ValueTask<string>(scope.Name); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the additional properties associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the additional properties associated with the scope.
|
|||
/// </returns>
|
|||
public virtual ValueTask<JObject> GetPropertiesAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(scope.Properties)) |
|||
{ |
|||
return new ValueTask<JObject>(new JObject()); |
|||
} |
|||
|
|||
return new ValueTask<JObject>(JObject.Parse(scope.Properties)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the resources associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the resources associated with the scope.
|
|||
/// </returns>
|
|||
public virtual ValueTask<ImmutableArray<string>> GetResourcesAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(scope.Resources)) |
|||
{ |
|||
return new ValueTask<ImmutableArray<string>>(ImmutableArray.Create<string>()); |
|||
} |
|||
|
|||
// Note: parsing the stringified resources is an expensive operation.
|
|||
// To mitigate that, the resulting array is stored in the memory cache.
|
|||
var key = string.Concat("b6148250-aede-4fb9-a621-07c9bcf238c3", "\x1e", scope.Resources); |
|||
var resources = Cache.GetOrCreate(key, entry => |
|||
{ |
|||
entry.SetPriority(CacheItemPriority.High) |
|||
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); |
|||
|
|||
return JArray.Parse(scope.Resources) |
|||
.Select(element => (string) element) |
|||
.ToImmutableArray(); |
|||
}); |
|||
|
|||
return new ValueTask<ImmutableArray<string>>(resources); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Instantiates a new scope.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the instantiated scope, that can be persisted in the database.
|
|||
/// </returns>
|
|||
public virtual ValueTask<TScope> InstantiateAsync(CancellationToken cancellationToken) |
|||
=> new ValueTask<TScope>(new TScope()); |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns all the corresponding elements.
|
|||
/// </summary>
|
|||
/// <param name="count">The number of results to return.</param>
|
|||
/// <param name="offset">The number of results to skip.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the elements returned when executing the specified query.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TScope>> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken) |
|||
{ |
|||
IQueryable<TScope> Query(IQueryable<TScope> scopes, int? skip, int? take) |
|||
{ |
|||
var query = scopes.OrderBy(scope => scope.Id).AsQueryable(); |
|||
|
|||
if (skip.HasValue) |
|||
{ |
|||
query = query.Skip(skip.Value); |
|||
} |
|||
|
|||
if (take.HasValue) |
|||
{ |
|||
query = query.Take(take.Value); |
|||
} |
|||
|
|||
return query; |
|||
} |
|||
|
|||
return ListAsync((scopes, state) => Query(scopes, state.offset, state.count), (offset, count), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns all the corresponding elements.
|
|||
/// </summary>
|
|||
/// <typeparam name="TState">The state type.</typeparam>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="state">The optional state.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the elements returned when executing the specified query.
|
|||
/// </returns>
|
|||
public abstract Task<ImmutableArray<TResult>> ListAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TScope>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Sets the description associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="description">The description associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetDescriptionAsync([NotNull] TScope scope, [CanBeNull] string description, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
scope.Description = description; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the display name associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="name">The display name associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetDisplayNameAsync([NotNull] TScope scope, [CanBeNull] string name, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
scope.DisplayName = name; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the name associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="name">The name associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetNameAsync([NotNull] TScope scope, [CanBeNull] string name, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
scope.Name = name; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the additional properties associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="properties">The additional properties associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetPropertiesAsync([NotNull] TScope scope, [CanBeNull] JObject properties, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
if (properties == null) |
|||
{ |
|||
scope.Properties = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
scope.Properties = properties.ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the resources associated with a scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope.</param>
|
|||
/// <param name="resources">The resources associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetResourcesAsync([NotNull] TScope scope, ImmutableArray<string> resources, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
if (resources.IsDefaultOrEmpty) |
|||
{ |
|||
scope.Resources = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
scope.Resources = new JArray(resources.ToArray()).ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Updates an existing scope.
|
|||
/// </summary>
|
|||
/// <param name="scope">The scope to update.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task UpdateAsync([NotNull] TScope scope, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Converts the provided identifier to a strongly typed key object.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The identifier to convert.</param>
|
|||
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
|
|||
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the provided identifier to its string representation.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The identifier to convert.</param>
|
|||
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
|
|||
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) |
|||
{ |
|||
if (Equals(identifier, default(TKey))) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier); |
|||
} |
|||
} |
|||
} |
|||
@ -1,805 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.ComponentModel; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace OpenIddict.Stores |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the tokens stored in a database.
|
|||
/// Note: this base class can only be used with the default OpenIddict entities.
|
|||
/// </summary>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public abstract class OpenIddictTokenStore<TToken, TApplication, TAuthorization, TKey> : IOpenIddictTokenStore<TToken> |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization>, new() |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken>, new() |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken>, new() |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
protected OpenIddictTokenStore([NotNull] IMemoryCache cache) |
|||
{ |
|||
if (cache == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(cache)); |
|||
} |
|||
|
|||
Cache = cache; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the memory cached associated with the current store.
|
|||
/// </summary>
|
|||
protected IMemoryCache Cache { get; } |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of tokens that exist in the database.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of applications in the database.
|
|||
/// </returns>
|
|||
public virtual Task<long> CountAsync(CancellationToken cancellationToken) |
|||
{ |
|||
return CountAsync(tokens => tokens, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines the number of tokens that match the specified query.
|
|||
/// </summary>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of tokens that match the specified query.
|
|||
/// </returns>
|
|||
public abstract Task<long> CountAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Creates a new token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to create.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task CreateAsync([NotNull] TToken token, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to delete.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public abstract Task DeleteAsync([NotNull] TToken token, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified application identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The application identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified application.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TToken>> FindByApplicationIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
IQueryable<TToken> Query(IQueryable<TToken> tokens, TKey key) |
|||
=> from token in tokens |
|||
where token.Application != null && |
|||
token.Application.Id.Equals(key) |
|||
select token; |
|||
|
|||
return ListAsync((tokens, key) => Query(tokens, key), ConvertIdentifierFromString(identifier), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified authorization identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The authorization identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified authorization.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TToken>> FindByAuthorizationIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
IQueryable<TToken> Query(IQueryable<TToken> tokens, TKey key) |
|||
=> from token in tokens |
|||
where token.Authorization != null && |
|||
token.Authorization.Id.Equals(key) |
|||
select token; |
|||
|
|||
return ListAsync((tokens, key) => Query(tokens, key), ConvertIdentifierFromString(identifier), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a token using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the token corresponding to the unique identifier.
|
|||
/// </returns>
|
|||
public virtual Task<TToken> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
IQueryable<TToken> Query(IQueryable<TToken> tokens, TKey key) |
|||
=> from token in tokens |
|||
where token.Id.Equals(key) |
|||
select token; |
|||
|
|||
return GetAsync((tokens, key) => Query(tokens, key), ConvertIdentifierFromString(identifier), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified reference identifier.
|
|||
/// Note: the reference identifier may be hashed or encrypted for security reasons.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The reference identifier associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified reference identifier.
|
|||
/// </returns>
|
|||
public virtual Task<TToken> FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
IQueryable<TToken> Query(IQueryable<TToken> tokens, string id) |
|||
=> from token in tokens |
|||
where token.ReferenceId == id |
|||
select token; |
|||
|
|||
return GetAsync((tokens, id) => Query(tokens, identifier), identifier, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of tokens corresponding to the specified subject.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the tokens.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the tokens corresponding to the specified subject.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TToken>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
IQueryable<TToken> Query(IQueryable<TToken> tokens, string principal) |
|||
=> from token in tokens |
|||
where token.Subject == principal |
|||
select token; |
|||
|
|||
return ListAsync((tokens, principal) => Query(tokens, principal), subject, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns the first element.
|
|||
/// </summary>
|
|||
/// <typeparam name="TState">The state type.</typeparam>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="state">The optional state.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the first element returned when executing the query.
|
|||
/// </returns>
|
|||
public abstract Task<TResult> GetAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TToken>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the optional application identifier associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the application identifier associated with the token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
if (token.Application != null) |
|||
{ |
|||
return new ValueTask<string>(ConvertIdentifierToString(token.Application.Id)); |
|||
} |
|||
|
|||
async Task<string> RetrieveApplicationIdAsync() |
|||
{ |
|||
IQueryable<TKey> Query(IQueryable<TToken> tokens, TKey key) |
|||
=> from element in tokens |
|||
where element.Id.Equals(key) && |
|||
element.Application != null |
|||
select element.Application.Id; |
|||
|
|||
return ConvertIdentifierToString(await GetAsync((tokens, key) => Query(tokens, key), token.Id, cancellationToken)); |
|||
} |
|||
|
|||
return new ValueTask<string>(RetrieveApplicationIdAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the optional authorization identifier associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorization identifier associated with the token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
if (token.Authorization != null) |
|||
{ |
|||
return new ValueTask<string>(ConvertIdentifierToString(token.Authorization.Id)); |
|||
} |
|||
|
|||
async Task<string> RetrieveAuthorizationIdAsync() |
|||
{ |
|||
IQueryable<TKey> Query(IQueryable<TToken> tokens, TKey key) |
|||
=> from element in tokens |
|||
where element.Id.Equals(key) && |
|||
element.Authorization != null |
|||
select element.Authorization.Id; |
|||
|
|||
return ConvertIdentifierToString(await GetAsync((tokens, key) => Query(tokens, key), token.Id, cancellationToken)); |
|||
} |
|||
|
|||
return new ValueTask<string>(RetrieveAuthorizationIdAsync()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the creation date associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the creation date associated with the specified token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return new ValueTask<DateTimeOffset?>(token.CreationDate); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the expiration date associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the expiration date associated with the specified token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<DateTimeOffset?> GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return new ValueTask<DateTimeOffset?>(token.ExpirationDate); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the unique identifier associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the unique identifier associated with the token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return new ValueTask<string>(ConvertIdentifierToString(token.Id)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the payload associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the payload associated with the specified token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetPayloadAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return new ValueTask<string>(token.Payload); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the additional properties associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the additional properties associated with the token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<JObject> GetPropertiesAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(token.Properties)) |
|||
{ |
|||
return new ValueTask<JObject>(new JObject()); |
|||
} |
|||
|
|||
return new ValueTask<JObject>(JObject.Parse(token.Properties)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the reference identifier associated with a token.
|
|||
/// Note: depending on the manager used to create the token,
|
|||
/// the reference identifier may be hashed for security reasons.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the reference identifier associated with the specified token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetReferenceIdAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return new ValueTask<string>(token.ReferenceId); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the status associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the status associated with the specified token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetStatusAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return new ValueTask<string>(token.Status); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the subject associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the subject associated with the specified token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetSubjectAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return new ValueTask<string>(token.Subject); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the token type associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the token type associated with the specified token.
|
|||
/// </returns>
|
|||
public virtual ValueTask<string> GetTokenTypeAsync([NotNull] TToken token, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
return new ValueTask<string>(token.Type); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Instantiates a new token.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the instantiated token, that can be persisted in the database.
|
|||
/// </returns>
|
|||
public virtual ValueTask<TToken> InstantiateAsync(CancellationToken cancellationToken) |
|||
=> new ValueTask<TToken>(new TToken()); |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns all the corresponding elements.
|
|||
/// </summary>
|
|||
/// <param name="count">The number of results to return.</param>
|
|||
/// <param name="offset">The number of results to skip.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the elements returned when executing the specified query.
|
|||
/// </returns>
|
|||
public virtual Task<ImmutableArray<TToken>> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken) |
|||
{ |
|||
IQueryable<TToken> Query(IQueryable<TToken> tokens, int? skip, int? take) |
|||
{ |
|||
var query = tokens.OrderBy(token => token.Id).AsQueryable(); |
|||
|
|||
if (skip.HasValue) |
|||
{ |
|||
query = query.Skip(skip.Value); |
|||
} |
|||
|
|||
if (take.HasValue) |
|||
{ |
|||
query = query.Take(take.Value); |
|||
} |
|||
|
|||
return query; |
|||
} |
|||
|
|||
return ListAsync((tokens, state) => Query(tokens, state.offset, state.count), (offset, count), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the specified query and returns all the corresponding elements.
|
|||
/// </summary>
|
|||
/// <typeparam name="TState">The state type.</typeparam>
|
|||
/// <typeparam name="TResult">The result type.</typeparam>
|
|||
/// <param name="query">The query to execute.</param>
|
|||
/// <param name="state">The optional state.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns all the elements returned when executing the specified query.
|
|||
/// </returns>
|
|||
public abstract Task<ImmutableArray<TResult>> ListAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TToken>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Removes the tokens that are marked as expired or invalid.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task PruneAsync(CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Sets the authorization identifier associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="identifier">The unique identifier associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Sets the application identifier associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="identifier">The unique identifier associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Sets the creation date associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="date">The creation date.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetCreationDateAsync([NotNull] TToken token, |
|||
[CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
token.CreationDate = date; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the expiration date associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="date">The expiration date.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetExpirationDateAsync([NotNull] TToken token, |
|||
[CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
token.ExpirationDate = date; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the payload associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="payload">The payload associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetPayloadAsync([NotNull] TToken token, [CanBeNull] string payload, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
token.Payload = payload; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the additional properties associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="properties">The additional properties associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetPropertiesAsync([NotNull] TToken token, [CanBeNull] JObject properties, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
if (properties == null) |
|||
{ |
|||
token.Properties = null; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
token.Properties = properties.ToString(Formatting.None); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the reference identifier associated with a token.
|
|||
/// Note: depending on the manager used to create the token,
|
|||
/// the reference identifier may be hashed for security reasons.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="identifier">The reference identifier associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetReferenceIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
token.ReferenceId = identifier; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the status associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="status">The status associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetStatusAsync([NotNull] TToken token, [CanBeNull] string status, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(status)) |
|||
{ |
|||
throw new ArgumentException("The status cannot be null or empty.", nameof(status)); |
|||
} |
|||
|
|||
token.Status = status; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the subject associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="subject">The subject associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetSubjectAsync([NotNull] TToken token, [CanBeNull] string subject, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
token.Subject = subject; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the token type associated with a token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token.</param>
|
|||
/// <param name="type">The token type associated with the token.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public virtual Task SetTokenTypeAsync([NotNull] TToken token, [CanBeNull] string type, CancellationToken cancellationToken) |
|||
{ |
|||
if (token == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(token)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(type)) |
|||
{ |
|||
throw new ArgumentException("The token type cannot be null or empty.", nameof(type)); |
|||
} |
|||
|
|||
token.Type = type; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Updates an existing token.
|
|||
/// </summary>
|
|||
/// <param name="token">The token to update.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
|
|||
/// </returns>
|
|||
public abstract Task UpdateAsync([NotNull] TToken token, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Converts the provided identifier to a strongly typed key object.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The identifier to convert.</param>
|
|||
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided identifier.</returns>
|
|||
public virtual TKey ConvertIdentifierFromString([CanBeNull] string identifier) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
return (TKey) TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(identifier); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the provided identifier to its string representation.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The identifier to convert.</param>
|
|||
/// <returns>A <see cref="string"/> representation of the provided identifier.</returns>
|
|||
public virtual string ConvertIdentifierToString([CanBeNull] TKey identifier) |
|||
{ |
|||
if (Equals(identifier, default(TKey))) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return TypeDescriptor.GetConverter(typeof(TKey)).ConvertToInvariantString(identifier); |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
/* |
|||
* 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 JetBrains.Annotations; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
public static class OpenIddictExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Configures OpenIddict to use the default entities, with the default entity key type (string).
|
|||
/// The default entities are <see cref="OpenIddictApplication"/>, <see cref="OpenIddictAuthorization"/>,
|
|||
/// <see cref="OpenIddictScope"/> and <see cref="OpenIddictToken"/>.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services</param>
|
|||
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
|
|||
public static OpenIddictCoreBuilder UseDefaultModels([NotNull] this OpenIddictCoreBuilder builder) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
return builder.UseCustomModels<OpenIddictApplication, |
|||
OpenIddictAuthorization, |
|||
OpenIddictScope, |
|||
OpenIddictToken>(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Configures OpenIddict to use the default entities, with the specified entity key type.
|
|||
/// The default entities are <see cref="OpenIddictApplication{TKey}"/>, <see cref="OpenIddictAuthorization{TKey}"/>,
|
|||
/// <see cref="OpenIddictScope{TKey}"/> and <see cref="OpenIddictToken{TKey}"/>.
|
|||
/// </summary>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services</param>
|
|||
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
|
|||
public static OpenIddictCoreBuilder UseDefaultModels<TKey>([NotNull] this OpenIddictCoreBuilder builder) |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
return builder.UseCustomModels<OpenIddictApplication<TKey>, |
|||
OpenIddictAuthorization<TKey>, |
|||
OpenIddictScope<TKey>, |
|||
OpenIddictToken<TKey>>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
/* |
|||
* 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 Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using OpenIddict.Core; |
|||
using OpenIddict.EntityFramework; |
|||
using OpenIddict.EntityFramework.Models; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.EntityFramework.Tests |
|||
{ |
|||
public class OpenIddictEntityFrameworkExtensionsTests |
|||
{ |
|||
[Theory] |
|||
[InlineData(typeof(OpenIddictApplicationStoreResolver))] |
|||
[InlineData(typeof(OpenIddictAuthorizationStoreResolver))] |
|||
[InlineData(typeof(OpenIddictScopeStoreResolver))] |
|||
[InlineData(typeof(OpenIddictTokenStoreResolver))] |
|||
public void AddEntityFrameworkStores_RegistersEntityFrameworkStoreFactories(Type type) |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var builder = services.AddOpenIddict().AddCore(); |
|||
|
|||
// Act
|
|||
builder.UseEntityFramework(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(services, service => service.ImplementationType == type); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UseEntityFrameworkModels_KeyTypeDefaultsToString() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var builder = services.AddOpenIddict().AddCore(); |
|||
|
|||
// Act
|
|||
builder.UseEntityFramework(); |
|||
|
|||
// Assert
|
|||
var provider = services.BuildServiceProvider(); |
|||
var options = provider.GetRequiredService<IOptionsMonitor<OpenIddictCoreOptions>>().CurrentValue; |
|||
|
|||
Assert.Equal(typeof(OpenIddictApplication), options.DefaultApplicationType); |
|||
Assert.Equal(typeof(OpenIddictAuthorization), options.DefaultAuthorizationType); |
|||
Assert.Equal(typeof(OpenIddictScope), options.DefaultScopeType); |
|||
Assert.Equal(typeof(OpenIddictToken), options.DefaultTokenType); |
|||
} |
|||
} |
|||
} |
|||
@ -1,35 +0,0 @@ |
|||
/* |
|||
* 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.Data.Entity; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using OpenIddict.EntityFramework; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.EntityFrameworkCore.Tests |
|||
{ |
|||
public class OpenIddictExtensionsTests |
|||
{ |
|||
[Theory] |
|||
[InlineData(typeof(OpenIddictApplicationStoreResolver<DbContext>))] |
|||
[InlineData(typeof(OpenIddictAuthorizationStoreResolver<DbContext>))] |
|||
[InlineData(typeof(OpenIddictScopeStoreResolver<DbContext>))] |
|||
[InlineData(typeof(OpenIddictTokenStoreResolver<DbContext>))] |
|||
public void AddEntityFrameworkStores_RegistersEntityFrameworkStoreFactories(Type type) |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var builder = services.AddOpenIddict().AddCore(); |
|||
|
|||
// Act
|
|||
builder.AddEntityFrameworkStores<DbContext>(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(services, service => service.ImplementationType == type); |
|||
} |
|||
} |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
/* |
|||
* 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 Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.EntityFrameworkCore.Tests |
|||
{ |
|||
public class OpenIddictExtensionsTests |
|||
{ |
|||
[Theory] |
|||
[InlineData(typeof(OpenIddictApplicationStoreResolver<DbContext>))] |
|||
[InlineData(typeof(OpenIddictAuthorizationStoreResolver<DbContext>))] |
|||
[InlineData(typeof(OpenIddictScopeStoreResolver<DbContext>))] |
|||
[InlineData(typeof(OpenIddictTokenStoreResolver<DbContext>))] |
|||
public void AddEntityFrameworkCoreStores_RegistersEntityFrameworkCoreStoreFactories(Type type) |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var builder = services.AddOpenIddict().AddCore(); |
|||
|
|||
// Act
|
|||
builder.AddEntityFrameworkCoreStores<DbContext>(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(services, service => service.ImplementationType == type); |
|||
} |
|||
} |
|||
} |
|||
@ -1,27 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\build\tests.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks> |
|||
<TargetFrameworks Condition=" $([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToReferenceAssemblies('.NETFramework', '4.7', '').Count) != 0 ">$(TargetFrameworks);net47</TargetFrameworks> |
|||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\OpenIddict\OpenIddict.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(AspNetCoreVersion)" /> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" /> |
|||
<PackageReference Include="Moq" Version="$(MoqVersion)" /> |
|||
<PackageReference Include="xunit" Version="$(XunitVersion)" /> |
|||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
Loading…
Reference in new issue