34 changed files with 0 additions and 6201 deletions
@ -1,12 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<Description>Relational entities for the NHibernate 5.x stores.</Description> |
|||
<PackageTags>$(PackageTags);nhibernate;models</PackageTags> |
|||
</PropertyGroup> |
|||
|
|||
</Project> |
|||
@ -1,120 +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.Generic; |
|||
using System.Diagnostics; |
|||
|
|||
namespace OpenIddict.NHibernate.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> : OpenIddictApplication<TKey, OpenIddictAuthorization<TKey>, OpenIddictToken<TKey>> |
|||
where TKey : IEquatable<TKey> |
|||
{ } |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict application.
|
|||
/// </summary>
|
|||
[DebuggerDisplay("Id = {Id.ToString(),nq} ; ClientId = {ClientId,nq} ; Type = {Type,nq}")] |
|||
public class OpenIddictApplication<TKey, TAuthorization, TToken> where TKey : IEquatable<TKey> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the list of the authorizations associated with this application.
|
|||
/// </summary>
|
|||
public virtual IList<TAuthorization> Authorizations { get; set; } = 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 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 or sets the requirements associated with the
|
|||
/// current application, serialized as a JSON array.
|
|||
/// </summary>
|
|||
public virtual string Requirements { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the list of the tokens associated with this application.
|
|||
/// </summary>
|
|||
public virtual IList<TToken> Tokens { get; set; } = new List<TToken>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the application type
|
|||
/// associated with the current application.
|
|||
/// </summary>
|
|||
public virtual string Type { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the entity version, used as a concurrency token.
|
|||
/// </summary>
|
|||
public virtual int Version { get; set; } |
|||
} |
|||
} |
|||
@ -1,87 +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.Generic; |
|||
using System.Diagnostics; |
|||
|
|||
namespace OpenIddict.NHibernate.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> : OpenIddictAuthorization<TKey, OpenIddictApplication<TKey>, OpenIddictToken<TKey>> |
|||
where TKey : IEquatable<TKey> |
|||
{ } |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict authorization.
|
|||
/// </summary>
|
|||
[DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; Type = {Type,nq} ; Status = {Status,nq}")] |
|||
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 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 or sets the list of tokens
|
|||
/// associated with the current authorization.
|
|||
/// </summary>
|
|||
public virtual IList<TToken> Tokens { get; set; } = new List<TToken>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the type of the current authorization.
|
|||
/// </summary>
|
|||
public virtual string Type { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the entity version, used as a concurrency token.
|
|||
/// </summary>
|
|||
public virtual int Version { get; set; } |
|||
} |
|||
} |
|||
@ -1,71 +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.Diagnostics; |
|||
|
|||
namespace OpenIddict.NHibernate.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>
|
|||
[DebuggerDisplay("Id = {Id.ToString(),nq} ; Name = {Name,nq}")] |
|||
public class OpenIddictScope<TKey> where TKey : IEquatable<TKey> |
|||
{ |
|||
/// <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; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the entity version, used as a concurrency token.
|
|||
/// </summary>
|
|||
public virtual int Version { get; set; } |
|||
} |
|||
} |
|||
@ -1,107 +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.Diagnostics; |
|||
|
|||
namespace OpenIddict.NHibernate.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> : OpenIddictToken<TKey, OpenIddictApplication<TKey>, OpenIddictAuthorization<TKey>> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an OpenIddict token.
|
|||
/// </summary>
|
|||
[DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; Type = {Type,nq} ; Status = {Status,nq}")] |
|||
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 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; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the entity version, used as a concurrency token.
|
|||
/// </summary>
|
|||
public virtual int Version { get; set; } |
|||
} |
|||
} |
|||
@ -1,27 +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.Threading; |
|||
using System.Threading.Tasks; |
|||
using NHibernate; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes the NHibernate session used by the OpenIddict stores.
|
|||
/// </summary>
|
|||
public interface IOpenIddictNHibernateContext |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="ISession"/>.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the
|
|||
/// asynchronous operation, whose result returns the NHibernate session.
|
|||
/// </returns>
|
|||
ValueTask<ISession> GetSessionAsync(CancellationToken cancellationToken); |
|||
} |
|||
} |
|||
@ -1,101 +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.ComponentModel; |
|||
using NHibernate.Mapping.ByCode; |
|||
using NHibernate.Mapping.ByCode.Conformist; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Defines a relational mapping for the Application entity.
|
|||
/// </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 Key entity.</typeparam>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public class OpenIddictApplicationMapping<TApplication, TAuthorization, TToken, TKey> : ClassMapping<TApplication> |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken> |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken> |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
public OpenIddictApplicationMapping() |
|||
{ |
|||
Id(application => application.Id, map => |
|||
{ |
|||
map.Generator(Generators.Identity); |
|||
}); |
|||
|
|||
Version(application => application.Version, map => |
|||
{ |
|||
map.Insert(true); |
|||
}); |
|||
|
|||
Property(application => application.ClientId, map => |
|||
{ |
|||
map.NotNullable(true); |
|||
map.Unique(true); |
|||
}); |
|||
|
|||
Property(application => application.ClientSecret); |
|||
|
|||
Property(application => application.ConsentType); |
|||
|
|||
Property(application => application.DisplayName); |
|||
|
|||
Property(application => application.Permissions, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(application => application.PostLogoutRedirectUris, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(application => application.Properties, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(application => application.RedirectUris, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(application => application.Type, map => |
|||
{ |
|||
map.NotNullable(true); |
|||
}); |
|||
|
|||
Bag(application => application.Authorizations, |
|||
map => |
|||
{ |
|||
map.Key(key => key.Column("ApplicationId")); |
|||
}, |
|||
map => |
|||
{ |
|||
map.OneToMany(); |
|||
}); |
|||
|
|||
Bag(application => application.Tokens, |
|||
map => |
|||
{ |
|||
map.Key(key => key.Column("ApplicationId")); |
|||
}, |
|||
map => |
|||
{ |
|||
map.OneToMany(); |
|||
}); |
|||
|
|||
Table("OpenIddictApplications"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,79 +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.ComponentModel; |
|||
using NHibernate.Mapping.ByCode; |
|||
using NHibernate.Mapping.ByCode.Conformist; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Defines a relational mapping for the Authorization entity.
|
|||
/// </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 Key entity.</typeparam>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public class OpenIddictAuthorizationMapping<TAuthorization, TApplication, TToken, TKey> : ClassMapping<TAuthorization> |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken> |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken> |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
public OpenIddictAuthorizationMapping() |
|||
{ |
|||
Id(authorization => authorization.Id, map => |
|||
{ |
|||
map.Generator(Generators.Identity); |
|||
}); |
|||
|
|||
Version(authorization => authorization.Version, map => |
|||
{ |
|||
map.Insert(true); |
|||
}); |
|||
|
|||
Property(authorization => authorization.Properties, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(authorization => authorization.Scopes, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(authorization => authorization.Status, map => |
|||
{ |
|||
map.NotNullable(true); |
|||
}); |
|||
|
|||
Property(authorization => authorization.Type, map => |
|||
{ |
|||
map.NotNullable(true); |
|||
}); |
|||
|
|||
ManyToOne(authorization => authorization.Application, map => |
|||
{ |
|||
map.ForeignKey("ApplicationId"); |
|||
}); |
|||
|
|||
Bag(authorization => authorization.Tokens, |
|||
map => |
|||
{ |
|||
map.Key(key => key.Column("AuthorizationId")); |
|||
}, |
|||
map => |
|||
{ |
|||
map.OneToMany(); |
|||
}); |
|||
|
|||
Table("OpenIddictAuthorizations"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,63 +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.ComponentModel; |
|||
using NHibernate.Mapping.ByCode; |
|||
using NHibernate.Mapping.ByCode.Conformist; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Defines a relational mapping for the Scope entity.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the Key entity.</typeparam>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public class OpenIddictScopeMapping<TScope, TKey> : ClassMapping<TScope> |
|||
where TScope : OpenIddictScope<TKey> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
public OpenIddictScopeMapping() |
|||
{ |
|||
Id(scope => scope.Id, map => |
|||
{ |
|||
map.Generator(Generators.Identity); |
|||
}); |
|||
|
|||
Version(scope => scope.Version, map => |
|||
{ |
|||
map.Insert(true); |
|||
}); |
|||
|
|||
Property(scope => scope.Description, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(scope => scope.DisplayName); |
|||
|
|||
Property(scope => scope.Name, map => |
|||
{ |
|||
map.NotNullable(true); |
|||
map.Unique(true); |
|||
}); |
|||
|
|||
Property(scope => scope.Properties, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(scope => scope.Resources, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Table("OpenIddictScopes"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,80 +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.ComponentModel; |
|||
using NHibernate.Mapping.ByCode; |
|||
using NHibernate.Mapping.ByCode.Conformist; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Defines a relational mapping for the Token entity.
|
|||
/// </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 Key entity.</typeparam>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public class OpenIddictTokenMapping<TToken, TApplication, TAuthorization, TKey> : ClassMapping<TToken> |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization> |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken> |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
public OpenIddictTokenMapping() |
|||
{ |
|||
Id(token => token.Id, map => |
|||
{ |
|||
map.Generator(Generators.Identity); |
|||
}); |
|||
|
|||
Version(token => token.Version, map => |
|||
{ |
|||
map.Insert(true); |
|||
}); |
|||
|
|||
Property(token => token.CreationDate); |
|||
|
|||
Property(token => token.ExpirationDate); |
|||
|
|||
Property(token => token.Payload, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(token => token.Properties, map => |
|||
{ |
|||
map.Length(10000); |
|||
}); |
|||
|
|||
Property(token => token.ReferenceId); |
|||
|
|||
Property(token => token.Status, map => |
|||
{ |
|||
map.NotNullable(true); |
|||
}); |
|||
|
|||
Property(token => token.Type, map => |
|||
{ |
|||
map.NotNullable(true); |
|||
}); |
|||
|
|||
ManyToOne(token => token.Application, map => |
|||
{ |
|||
map.Column("ApplicationId"); |
|||
}); |
|||
|
|||
ManyToOne(token => token.Authorization, map => |
|||
{ |
|||
map.Column("AuthorizationId"); |
|||
}); |
|||
|
|||
Table("OpenIddictTokens"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,26 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup> |
|||
<Description>NHibernate 5.x stores for OpenIddict.</Description> |
|||
<PackageTags>$(PackageTags);nhibernate</PackageTags> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\OpenIddict.Core\OpenIddict.Core.csproj" /> |
|||
<ProjectReference Include="..\OpenIddict.NHibernate.Models\OpenIddict.NHibernate.Models.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="JetBrains.Annotations" Version="$(JetBrainsVersion)" PrivateAssets="All" /> |
|||
<PackageReference Include="NHibernate" Version="$(NHibernateVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Include="..\..\shared\OpenIddict.Extensions\*\*.cs" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,102 +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.ComponentModel; |
|||
using JetBrains.Annotations; |
|||
using NHibernate; |
|||
using OpenIddict.Core; |
|||
using OpenIddict.NHibernate; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes the necessary methods required to configure the OpenIddict NHibernate services.
|
|||
/// </summary>
|
|||
public class OpenIddictNHibernateBuilder |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of <see cref="OpenIddictNHibernateBuilder"/>.
|
|||
/// </summary>
|
|||
/// <param name="services">The services collection.</param>
|
|||
public OpenIddictNHibernateBuilder([NotNull] IServiceCollection services) |
|||
=> Services = services ?? throw new ArgumentNullException(nameof(services)); |
|||
|
|||
/// <summary>
|
|||
/// Gets the services collection.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public IServiceCollection Services { get; } |
|||
|
|||
/// <summary>
|
|||
/// Amends the default OpenIddict NHibernate 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="OpenIddictNHibernateBuilder"/>.</returns>
|
|||
public OpenIddictNHibernateBuilder Configure([NotNull] Action<OpenIddictNHibernateOptions> configuration) |
|||
{ |
|||
if (configuration == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(configuration)); |
|||
} |
|||
|
|||
Services.Configure(configuration); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Configures the NHibernate stores to use the specified session factory
|
|||
/// instead of retrieving it from the dependency injection container.
|
|||
/// </summary>
|
|||
/// <param name="factory">The <see cref="ISessionFactory"/>.</param>
|
|||
/// <returns>The <see cref="OpenIddictNHibernateBuilder"/>.</returns>
|
|||
public OpenIddictNHibernateBuilder UseSessionFactory([NotNull] ISessionFactory factory) |
|||
{ |
|||
if (factory == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(factory)); |
|||
} |
|||
|
|||
return Configure(options => options.SessionFactory = factory); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Configures OpenIddict to use the default OpenIddict Entity Framework entities, with the specified key type.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="OpenIddictNHibernateBuilder"/>.</returns>
|
|||
public OpenIddictNHibernateBuilder 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 entities.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="OpenIddictNHibernateBuilder"/>.</returns>
|
|||
public OpenIddictNHibernateBuilder ReplaceDefaultEntities<TApplication, TAuthorization, TScope, TToken, TKey>() |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken> |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken> |
|||
where TScope : OpenIddictScope<TKey> |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization> |
|||
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; |
|||
} |
|||
} |
|||
} |
|||
@ -1,125 +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.Text; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using NHibernate; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes the NHibernate session used by the OpenIddict stores.
|
|||
/// </summary>
|
|||
public class OpenIddictNHibernateContext : IOpenIddictNHibernateContext, IDisposable |
|||
{ |
|||
private readonly IOptionsMonitor<OpenIddictNHibernateOptions> _options; |
|||
private readonly IServiceProvider _provider; |
|||
private ISession _session; |
|||
|
|||
public OpenIddictNHibernateContext( |
|||
[NotNull] IOptionsMonitor<OpenIddictNHibernateOptions> options, |
|||
[NotNull] IServiceProvider provider) |
|||
{ |
|||
_options = options; |
|||
_provider = provider; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disposes the session held by this instance, if applicable.
|
|||
/// </summary>
|
|||
public void Dispose() => _session?.Dispose(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the <see cref="ISession"/>.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the
|
|||
/// asynchronous operation, whose result returns the NHibernate session.
|
|||
/// </returns>
|
|||
/// <remarks>
|
|||
/// If a session factory was explicitly set in the OpenIddict NHibernate options,
|
|||
/// a new session, specific to the OpenIddict stores is automatically opened
|
|||
/// and disposed when the ambient scope is collected. If no session factory
|
|||
/// was set, the session is retrieved from the dependency injection container
|
|||
/// and a derived instance disabling automatic flush is managed by the context.
|
|||
/// </remarks>
|
|||
public ValueTask<ISession> GetSessionAsync(CancellationToken cancellationToken) |
|||
{ |
|||
if (_session != null) |
|||
{ |
|||
return new ValueTask<ISession>(_session); |
|||
} |
|||
|
|||
if (cancellationToken.IsCancellationRequested) |
|||
{ |
|||
return new ValueTask<ISession>(Task.FromCanceled<ISession>(cancellationToken)); |
|||
} |
|||
|
|||
var options = _options.CurrentValue; |
|||
if (options == null) |
|||
{ |
|||
throw new InvalidOperationException("The OpenIddict NHibernate options cannot be retrieved."); |
|||
} |
|||
|
|||
// Note: by default, NHibernate is natively configured to perform automatic flushes
|
|||
// on queries when it determines stale data may be returned during their execution.
|
|||
// Combined with implicit entity updates, this feature is inconvenient for OpenIddict
|
|||
// as it may result in updated entities being persisted before they are explicitly
|
|||
// validated by the core managers and marked as updated by the NHibernate stores.
|
|||
// To ensure this doesn't interfere with OpenIddict, automatic flush is disabled.
|
|||
|
|||
var factory = options.SessionFactory; |
|||
if (factory == null) |
|||
{ |
|||
var session = _provider.GetService<ISession>(); |
|||
if (session != null) |
|||
{ |
|||
// If the flush mode is already set to manual, avoid creating a sub-session.
|
|||
// If the session must be derived, all the parameters are inherited from
|
|||
// the original session (except the flush mode, explicitly set to manual).
|
|||
if (session.FlushMode != FlushMode.Manual) |
|||
{ |
|||
session = _session = session.SessionWithOptions() |
|||
.AutoClose() |
|||
.AutoJoinTransaction() |
|||
.Connection() |
|||
.ConnectionReleaseMode() |
|||
.FlushMode(FlushMode.Manual) |
|||
.Interceptor() |
|||
.OpenSession(); |
|||
} |
|||
|
|||
return new ValueTask<ISession>(session); |
|||
} |
|||
|
|||
factory = _provider.GetService<ISessionFactory>(); |
|||
} |
|||
|
|||
if (factory == null) |
|||
{ |
|||
throw new InvalidOperationException(new StringBuilder() |
|||
.AppendLine("No suitable NHibernate session or session factory can be found.") |
|||
.Append("To configure the OpenIddict NHibernate stores to use a specific factory, use ") |
|||
.Append("'services.AddOpenIddict().AddCore().UseNHibernate().UseSessionFactory()' or register an ") |
|||
.Append("'ISession'/'ISessionFactory' in the dependency injection container in 'ConfigureServices()'.") |
|||
.ToString()); |
|||
} |
|||
|
|||
else |
|||
{ |
|||
var session = factory.OpenSession(); |
|||
session.FlushMode = FlushMode.Manual; |
|||
|
|||
return new ValueTask<ISession>(_session = session); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,91 +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 Microsoft.Extensions.DependencyInjection.Extensions; |
|||
using OpenIddict.NHibernate; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes extensions allowing to register the OpenIddict NHibernate services.
|
|||
/// </summary>
|
|||
public static class OpenIddictNHibernateExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Registers the NHibernate stores services in the DI container and
|
|||
/// configures OpenIddict to use the NHibernate entities by default.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictNHibernateBuilder"/>.</returns>
|
|||
public static OpenIddictNHibernateBuilder UseNHibernate([NotNull] this OpenIddictCoreBuilder builder) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
// Since NHibernate may be used with databases performing case-insensitive or
|
|||
// culture-sensitive comparisons, ensure the additional filtering logic is enforced
|
|||
// in case case-sensitive stores were registered before this extension was called.
|
|||
builder.Configure(options => options.DisableAdditionalFiltering = false); |
|||
|
|||
builder.SetDefaultApplicationEntity<OpenIddictApplication>() |
|||
.SetDefaultAuthorizationEntity<OpenIddictAuthorization>() |
|||
.SetDefaultScopeEntity<OpenIddictScope>() |
|||
.SetDefaultTokenEntity<OpenIddictToken>(); |
|||
|
|||
builder.ReplaceApplicationStoreResolver<OpenIddictApplicationStoreResolver>() |
|||
.ReplaceAuthorizationStoreResolver<OpenIddictAuthorizationStoreResolver>() |
|||
.ReplaceScopeStoreResolver<OpenIddictScopeStoreResolver>() |
|||
.ReplaceTokenStoreResolver<OpenIddictTokenStoreResolver>(); |
|||
|
|||
builder.Services.TryAddSingleton<OpenIddictApplicationStoreResolver.TypeResolutionCache>(); |
|||
builder.Services.TryAddSingleton<OpenIddictAuthorizationStoreResolver.TypeResolutionCache>(); |
|||
builder.Services.TryAddSingleton<OpenIddictScopeStoreResolver.TypeResolutionCache>(); |
|||
builder.Services.TryAddSingleton<OpenIddictTokenStoreResolver.TypeResolutionCache>(); |
|||
|
|||
builder.Services.TryAddScoped(typeof(OpenIddictApplicationStore<,,,>)); |
|||
builder.Services.TryAddScoped(typeof(OpenIddictAuthorizationStore<,,,>)); |
|||
builder.Services.TryAddScoped(typeof(OpenIddictScopeStore<,>)); |
|||
builder.Services.TryAddScoped(typeof(OpenIddictTokenStore<,,,>)); |
|||
|
|||
builder.Services.TryAddScoped<IOpenIddictNHibernateContext, OpenIddictNHibernateContext>(); |
|||
|
|||
return new OpenIddictNHibernateBuilder(builder.Services); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers the NHibernate stores services in the DI container and
|
|||
/// configures OpenIddict to use the NHibernate entities by default.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
|
|||
/// <param name="configuration">The configuration delegate used to configure the NHibernate services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
|
|||
public static OpenIddictCoreBuilder UseNHibernate( |
|||
[NotNull] this OpenIddictCoreBuilder builder, |
|||
[NotNull] Action<OpenIddictNHibernateBuilder> configuration) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
if (configuration == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(configuration)); |
|||
} |
|||
|
|||
configuration(builder.UseNHibernate()); |
|||
|
|||
return builder; |
|||
} |
|||
} |
|||
} |
|||
@ -1,103 +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.Generic; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using JetBrains.Annotations; |
|||
using NHibernate.Linq; |
|||
using NHibernate.Mapping.ByCode; |
|||
using OpenIddict.NHibernate; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace NHibernate.Cfg |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes extensions simplifying the integration between OpenIddict and NHibernate.
|
|||
/// </summary>
|
|||
public static class OpenIddictNHibernateHelpers |
|||
{ |
|||
/// <summary>
|
|||
/// Registers the OpenIddict entity mappings in the NHibernate
|
|||
/// configuration using the default entities and the default key type.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The NHibernate configuration builder.</param>
|
|||
/// <returns>The <see cref="Configuration"/>.</returns>
|
|||
public static Configuration UseOpenIddict([NotNull] this Configuration configuration) |
|||
=> configuration.UseOpenIddict<OpenIddictApplication, |
|||
OpenIddictAuthorization, |
|||
OpenIddictScope, |
|||
OpenIddictToken, string>(); |
|||
|
|||
/// <summary>
|
|||
/// Registers the OpenIddict entity mappings in the NHibernate
|
|||
/// configuration using the default entities and the specified key type.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The NHibernate configuration builder.</param>
|
|||
/// <returns>The <see cref="Configuration"/>.</returns>
|
|||
public static Configuration UseOpenIddict<TKey>([NotNull] this Configuration configuration) |
|||
where TKey : IEquatable<TKey> |
|||
=> configuration.UseOpenIddict<OpenIddictApplication<TKey>, |
|||
OpenIddictAuthorization<TKey>, |
|||
OpenIddictScope<TKey>, |
|||
OpenIddictToken<TKey>, TKey>(); |
|||
|
|||
/// <summary>
|
|||
/// Registers the OpenIddict entity mappings in the NHibernate
|
|||
/// configuration using the specified entities and the specified key type.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The NHibernate configuration builder.</param>
|
|||
/// <returns>The <see cref="Configuration"/>.</returns>
|
|||
public static Configuration UseOpenIddict<TApplication, TAuthorization, TScope, TToken, TKey>([NotNull] this Configuration configuration) |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken> |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken> |
|||
where TScope : OpenIddictScope<TKey> |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
if (configuration == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(configuration)); |
|||
} |
|||
|
|||
var mapper = new ModelMapper(); |
|||
mapper.AddMapping<OpenIddictApplicationMapping<TApplication, TAuthorization, TToken, TKey>>(); |
|||
mapper.AddMapping<OpenIddictAuthorizationMapping<TAuthorization, TApplication, TToken, TKey>>(); |
|||
mapper.AddMapping<OpenIddictScopeMapping<TScope, TKey>>(); |
|||
mapper.AddMapping<OpenIddictTokenMapping<TToken, TApplication, TAuthorization, TKey>>(); |
|||
|
|||
configuration.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities()); |
|||
|
|||
return configuration; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Executes the query and returns the results as a non-streamed async enumeration.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of the returned entities.</typeparam>
|
|||
/// <param name="source">The query source.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>The non-streamed async enumeration containing the results.</returns>
|
|||
internal static IAsyncEnumerable<T> AsAsyncEnumerable<T>([NotNull] this IQueryable<T> source, CancellationToken cancellationToken) |
|||
{ |
|||
if (source == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(source)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<T> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
foreach (var element in await source.ToListAsync(cancellationToken)) |
|||
{ |
|||
yield return element; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,22 +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 NHibernate; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Provides various settings needed to configure the OpenIddict NHibernate integration.
|
|||
/// </summary>
|
|||
public class OpenIddictNHibernateOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the session factory used by the OpenIddict NHibernate stores.
|
|||
/// If none is explicitly set, the session factory is resolved from the DI container.
|
|||
/// </summary>
|
|||
public ISessionFactory SessionFactory { get; set; } |
|||
} |
|||
} |
|||
@ -1,77 +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.Concurrent; |
|||
using System.Text; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Extensions; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes a method allowing to resolve an application store.
|
|||
/// </summary>
|
|||
public class OpenIddictApplicationStoreResolver : IOpenIddictApplicationStoreResolver |
|||
{ |
|||
private readonly TypeResolutionCache _cache; |
|||
private readonly IServiceProvider _provider; |
|||
|
|||
public OpenIddictApplicationStoreResolver( |
|||
[NotNull] TypeResolutionCache cache, |
|||
[NotNull] IServiceProvider provider) |
|||
{ |
|||
_cache = cache; |
|||
_provider = provider; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns an application store compatible with the specified application type or throws an
|
|||
/// <see cref="InvalidOperationException"/> if no store can be built using the specified type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|||
/// <returns>An <see cref="IOpenIddictApplicationStore{TApplication}"/>.</returns>
|
|||
public IOpenIddictApplicationStore<TApplication> Get<TApplication>() where TApplication : class |
|||
{ |
|||
var store = _provider.GetService<IOpenIddictApplicationStore<TApplication>>(); |
|||
if (store != null) |
|||
{ |
|||
return store; |
|||
} |
|||
|
|||
var type = _cache.GetOrAdd(typeof(TApplication), key => |
|||
{ |
|||
var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictApplication<,,>)); |
|||
if (root == null) |
|||
{ |
|||
throw new InvalidOperationException(new StringBuilder() |
|||
.AppendLine("The specified application type is not compatible with the NHibernate stores.") |
|||
.Append("When enabling the NHibernate stores, make sure you use the built-in ") |
|||
.Append("'OpenIddictApplication' entity (from the 'OpenIddict.NHibernate.Models' package) ") |
|||
.Append("or a custom entity that inherits from the generic 'OpenIddictApplication' entity.") |
|||
.ToString()); |
|||
} |
|||
|
|||
return typeof(OpenIddictApplicationStore<,,,>).MakeGenericType( |
|||
/* TApplication: */ key, |
|||
/* TAuthorization: */ root.GenericTypeArguments[1], |
|||
/* TToken: */ root.GenericTypeArguments[2], |
|||
/* TKey: */ root.GenericTypeArguments[0]); |
|||
}); |
|||
|
|||
return (IOpenIddictApplicationStore<TApplication>) _provider.GetRequiredService(type); |
|||
} |
|||
|
|||
// Note: NHibernate resolvers are registered as scoped dependencies as their inner
|
|||
// service provider must be able to resolve scoped services (typically, the store they return).
|
|||
// To avoid having to declare a static type resolution cache, a special cache service is used
|
|||
// here and registered as a singleton dependency so that its content persists beyond the scope.
|
|||
public class TypeResolutionCache : ConcurrentDictionary<Type, Type> { } |
|||
} |
|||
} |
|||
@ -1,77 +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.Concurrent; |
|||
using System.Text; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Extensions; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes a method allowing to resolve an authorization store.
|
|||
/// </summary>
|
|||
public class OpenIddictAuthorizationStoreResolver : IOpenIddictAuthorizationStoreResolver |
|||
{ |
|||
private readonly TypeResolutionCache _cache; |
|||
private readonly IServiceProvider _provider; |
|||
|
|||
public OpenIddictAuthorizationStoreResolver( |
|||
[NotNull] TypeResolutionCache cache, |
|||
[NotNull] IServiceProvider provider) |
|||
{ |
|||
_cache = cache; |
|||
_provider = provider; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns an authorization store compatible with the specified authorization type or throws an
|
|||
/// <see cref="InvalidOperationException"/> if no store can be built using the specified type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|||
/// <returns>An <see cref="IOpenIddictAuthorizationStore{TAuthorization}"/>.</returns>
|
|||
public IOpenIddictAuthorizationStore<TAuthorization> Get<TAuthorization>() where TAuthorization : class |
|||
{ |
|||
var store = _provider.GetService<IOpenIddictAuthorizationStore<TAuthorization>>(); |
|||
if (store != null) |
|||
{ |
|||
return store; |
|||
} |
|||
|
|||
var type = _cache.GetOrAdd(typeof(TAuthorization), key => |
|||
{ |
|||
var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictAuthorization<,,>)); |
|||
if (root == null) |
|||
{ |
|||
throw new InvalidOperationException(new StringBuilder() |
|||
.AppendLine("The specified authorization type is not compatible with the NHibernate stores.") |
|||
.Append("When enabling the NHibernate stores, make sure you use the built-in ") |
|||
.Append("'OpenIddictAuthorization' entity (from the 'OpenIddict.NHibernate.Models' package) ") |
|||
.Append("or a custom entity that inherits from the generic 'OpenIddictAuthorization' entity.") |
|||
.ToString()); |
|||
} |
|||
|
|||
return typeof(OpenIddictAuthorizationStore<,,,>).MakeGenericType( |
|||
/* TAuthorization: */ key, |
|||
/* TApplication: */ root.GenericTypeArguments[1], |
|||
/* TToken: */ root.GenericTypeArguments[2], |
|||
/* TKey: */ root.GenericTypeArguments[0]); |
|||
}); |
|||
|
|||
return (IOpenIddictAuthorizationStore<TAuthorization>) _provider.GetRequiredService(type); |
|||
} |
|||
|
|||
// Note: NHibernate resolvers are registered as scoped dependencies as their inner
|
|||
// service provider must be able to resolve scoped services (typically, the store they return).
|
|||
// To avoid having to declare a static type resolution cache, a special cache service is used
|
|||
// here and registered as a singleton dependency so that its content persists beyond the scope.
|
|||
public class TypeResolutionCache : ConcurrentDictionary<Type, Type> { } |
|||
} |
|||
} |
|||
@ -1,75 +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.Concurrent; |
|||
using System.Text; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Extensions; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes a method allowing to resolve a scope store.
|
|||
/// </summary>
|
|||
public class OpenIddictScopeStoreResolver : IOpenIddictScopeStoreResolver |
|||
{ |
|||
private readonly TypeResolutionCache _cache; |
|||
private readonly IServiceProvider _provider; |
|||
|
|||
public OpenIddictScopeStoreResolver( |
|||
[NotNull] TypeResolutionCache cache, |
|||
[NotNull] IServiceProvider provider) |
|||
{ |
|||
_cache = cache; |
|||
_provider = provider; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a scope store compatible with the specified scope type or throws an
|
|||
/// <see cref="InvalidOperationException"/> if no store can be built using the specified type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
/// <returns>An <see cref="IOpenIddictScopeStore{TScope}"/>.</returns>
|
|||
public IOpenIddictScopeStore<TScope> Get<TScope>() where TScope : class |
|||
{ |
|||
var store = _provider.GetService<IOpenIddictScopeStore<TScope>>(); |
|||
if (store != null) |
|||
{ |
|||
return store; |
|||
} |
|||
|
|||
var type = _cache.GetOrAdd(typeof(TScope), key => |
|||
{ |
|||
var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictScope<>)); |
|||
if (root == null) |
|||
{ |
|||
throw new InvalidOperationException(new StringBuilder() |
|||
.AppendLine("The specified scope type is not compatible with the NHibernate stores.") |
|||
.Append("When enabling the NHibernate stores, make sure you use the built-in ") |
|||
.Append("'OpenIddictScope' entity (from the 'OpenIddict.NHibernate.Models' package) ") |
|||
.Append("or a custom entity that inherits from the generic 'OpenIddictScope' entity.") |
|||
.ToString()); |
|||
} |
|||
|
|||
return typeof(OpenIddictScopeStore<,>).MakeGenericType( |
|||
/* TScope: */ key, |
|||
/* TKey: */ root.GenericTypeArguments[0]); |
|||
}); |
|||
|
|||
return (IOpenIddictScopeStore<TScope>) _provider.GetRequiredService(type); |
|||
} |
|||
|
|||
// Note: NHibernate resolvers are registered as scoped dependencies as their inner
|
|||
// service provider must be able to resolve scoped services (typically, the store they return).
|
|||
// To avoid having to declare a static type resolution cache, a special cache service is used
|
|||
// here and registered as a singleton dependency so that its content persists beyond the scope.
|
|||
public class TypeResolutionCache : ConcurrentDictionary<Type, Type> { } |
|||
} |
|||
} |
|||
@ -1,77 +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.Concurrent; |
|||
using System.Text; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Extensions; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes a method allowing to resolve a token store.
|
|||
/// </summary>
|
|||
public class OpenIddictTokenStoreResolver : IOpenIddictTokenStoreResolver |
|||
{ |
|||
private readonly TypeResolutionCache _cache; |
|||
private readonly IServiceProvider _provider; |
|||
|
|||
public OpenIddictTokenStoreResolver( |
|||
[NotNull] TypeResolutionCache cache, |
|||
[NotNull] IServiceProvider provider) |
|||
{ |
|||
_cache = cache; |
|||
_provider = provider; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a token store compatible with the specified token type or throws an
|
|||
/// <see cref="InvalidOperationException"/> if no store can be built using the specified type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|||
/// <returns>An <see cref="IOpenIddictTokenStore{TToken}"/>.</returns>
|
|||
public IOpenIddictTokenStore<TToken> Get<TToken>() where TToken : class |
|||
{ |
|||
var store = _provider.GetService<IOpenIddictTokenStore<TToken>>(); |
|||
if (store != null) |
|||
{ |
|||
return store; |
|||
} |
|||
|
|||
var type = _cache.GetOrAdd(typeof(TToken), key => |
|||
{ |
|||
var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictToken<,,>)); |
|||
if (root == null) |
|||
{ |
|||
throw new InvalidOperationException(new StringBuilder() |
|||
.AppendLine("The specified token type is not compatible with the NHibernate stores.") |
|||
.Append("When enabling the NHibernate stores, make sure you use the built-in ") |
|||
.Append("'OpenIddictToken' entity (from the 'OpenIddict.NHibernate.Models' package) ") |
|||
.Append("or a custom entity that inherits from the generic 'OpenIddictToken' entity.") |
|||
.ToString()); |
|||
} |
|||
|
|||
return typeof(OpenIddictTokenStore<,,,>).MakeGenericType( |
|||
/* TToken: */ key, |
|||
/* TApplication: */ root.GenericTypeArguments[1], |
|||
/* TAuthorization: */ root.GenericTypeArguments[2], |
|||
/* TKey: */ root.GenericTypeArguments[0]); |
|||
}); |
|||
|
|||
return (IOpenIddictTokenStore<TToken>) _provider.GetRequiredService(type); |
|||
} |
|||
|
|||
// Note: NHibernate resolvers are registered as scoped dependencies as their inner
|
|||
// service provider must be able to resolve scoped services (typically, the store they return).
|
|||
// To avoid having to declare a static type resolution cache, a special cache service is used
|
|||
// here and registered as a singleton dependency so that its content persists beyond the scope.
|
|||
public class TypeResolutionCache : ConcurrentDictionary<Type, Type> { } |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -1,950 +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.Generic; |
|||
using System.Collections.Immutable; |
|||
using System.ComponentModel; |
|||
using System.Linq; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Text; |
|||
using System.Text.Encodings.Web; |
|||
using System.Text.Json; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.Options; |
|||
using NHibernate; |
|||
using NHibernate.Cfg; |
|||
using NHibernate.Linq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the authorizations stored in a database.
|
|||
/// </summary>
|
|||
public class OpenIddictAuthorizationStore : OpenIddictAuthorizationStore<OpenIddictAuthorization, |
|||
OpenIddictApplication, |
|||
OpenIddictToken, string> |
|||
{ |
|||
public OpenIddictAuthorizationStore( |
|||
[NotNull] IMemoryCache cache, |
|||
[NotNull] IOpenIddictNHibernateContext context, |
|||
[NotNull] IOptionsMonitor<OpenIddictNHibernateOptions> options) |
|||
: base(cache, context, options) |
|||
{ |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the authorizations stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public class OpenIddictAuthorizationStore<TKey> : OpenIddictAuthorizationStore<OpenIddictAuthorization<TKey>, |
|||
OpenIddictApplication<TKey>, |
|||
OpenIddictToken<TKey>, TKey> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
public OpenIddictAuthorizationStore( |
|||
[NotNull] IMemoryCache cache, |
|||
[NotNull] IOpenIddictNHibernateContext context, |
|||
[NotNull] IOptionsMonitor<OpenIddictNHibernateOptions> options) |
|||
: base(cache, context, options) |
|||
{ |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the authorizations stored in a database.
|
|||
/// </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 class OpenIddictAuthorizationStore<TAuthorization, TApplication, TToken, TKey> : IOpenIddictAuthorizationStore<TAuthorization> |
|||
where TAuthorization : OpenIddictAuthorization<TKey, TApplication, TToken> |
|||
where TApplication : OpenIddictApplication<TKey, TAuthorization, TToken> |
|||
where TToken : OpenIddictToken<TKey, TApplication, TAuthorization> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
public OpenIddictAuthorizationStore( |
|||
[NotNull] IMemoryCache cache, |
|||
[NotNull] IOpenIddictNHibernateContext context, |
|||
[NotNull] IOptionsMonitor<OpenIddictNHibernateOptions> options) |
|||
{ |
|||
Cache = cache; |
|||
Context = context; |
|||
Options = options; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the memory cache associated with the current store.
|
|||
/// </summary>
|
|||
protected IMemoryCache Cache { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the database context associated with the current store.
|
|||
/// </summary>
|
|||
protected IOpenIddictNHibernateContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the options associated with the current store.
|
|||
/// </summary>
|
|||
protected IOptionsMonitor<OpenIddictNHibernateOptions> Options { 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="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of authorizations in the database.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<long> CountAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
return await session.Query<TAuthorization>().LongCountAsync(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="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of authorizations that match the specified query.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<long> CountAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken) |
|||
{ |
|||
if (query == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(query)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
return await query(session.Query<TAuthorization>()).LongCountAsync(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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async ValueTask CreateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
await session.SaveAsync(authorization, cancellationToken); |
|||
await session.FlushAsync(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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async ValueTask DeleteAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
try |
|||
{ |
|||
// Delete all the tokens associated with the authorization.
|
|||
await (from token in session.Query<TToken>() |
|||
where token.Authorization.Id.Equals(authorization.Id) |
|||
select token).DeleteAsync(cancellationToken); |
|||
|
|||
await session.DeleteAsync(authorization, cancellationToken); |
|||
await session.FlushAsync(cancellationToken); |
|||
} |
|||
|
|||
catch (StaleObjectStateException exception) |
|||
{ |
|||
throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() |
|||
.AppendLine("The authorization was concurrently updated and cannot be persisted in its current state.") |
|||
.Append("Reload the authorization from the database and retry the operation.") |
|||
.ToString(), exception); |
|||
} |
|||
} |
|||
|
|||
/// <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>The authorizations corresponding to the subject/client.</returns>
|
|||
public virtual IAsyncEnumerable<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)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TAuthorization> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
var key = ConvertIdentifierFromString(client); |
|||
|
|||
await foreach (var authorization in |
|||
(from authorization in session.Query<TAuthorization>().Fetch(authorization => authorization.Application) |
|||
where authorization.Application != null && |
|||
authorization.Application.Id.Equals(key) && |
|||
authorization.Subject == subject |
|||
select authorization).AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return authorization; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <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>The authorizations corresponding to the criteria.</returns>
|
|||
public virtual IAsyncEnumerable<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)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TAuthorization> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
var key = ConvertIdentifierFromString(client); |
|||
|
|||
await foreach (var authorization in |
|||
(from authorization in session.Query<TAuthorization>().Fetch(authorization => authorization.Application) |
|||
where authorization.Application != null && |
|||
authorization.Application.Id.Equals(key) && |
|||
authorization.Subject == subject && |
|||
authorization.Status == status |
|||
select authorization).AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return authorization; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <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>The authorizations corresponding to the criteria.</returns>
|
|||
public virtual IAsyncEnumerable<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)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TAuthorization> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
var key = ConvertIdentifierFromString(client); |
|||
|
|||
await foreach (var authorization in |
|||
(from authorization in session.Query<TAuthorization>().Fetch(authorization => authorization.Application) |
|||
where authorization.Application != null && |
|||
authorization.Application.Id.Equals(key) && |
|||
authorization.Subject == subject && |
|||
authorization.Status == status && |
|||
authorization.Type == type |
|||
select authorization).AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return authorization; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the authorizations matching the specified parameters.
|
|||
/// </summary>
|
|||
/// <param name="subject">The subject associated with the authorization.</param>
|
|||
/// <param name="client">The client associated with the authorization.</param>
|
|||
/// <param name="status">The authorization status.</param>
|
|||
/// <param name="type">The authorization type.</param>
|
|||
/// <param name="scopes">The minimal scopes associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>The authorizations corresponding to the criteria.</returns>
|
|||
public virtual IAsyncEnumerable<TAuthorization> FindAsync( |
|||
[NotNull] string subject, [NotNull] string client, |
|||
[NotNull] string status, [NotNull] string type, |
|||
ImmutableArray<string> scopes, CancellationToken cancellationToken) |
|||
=> FindAsync(subject, client, status, type, cancellationToken) |
|||
.WhereAwait(async authorization => new HashSet<string>( |
|||
await GetScopesAsync(authorization, cancellationToken), StringComparer.Ordinal).IsSupersetOf(scopes)); |
|||
|
|||
/// <summary>
|
|||
/// Retrieves the list of authorizations corresponding to the specified application identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The application identifier associated with the authorizations.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>The authorizations corresponding to the specified application.</returns>
|
|||
public virtual IAsyncEnumerable<TAuthorization> FindByApplicationIdAsync( |
|||
[NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TAuthorization> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
var key = ConvertIdentifierFromString(identifier); |
|||
|
|||
await foreach (var authorization in |
|||
(from authorization in session.Query<TAuthorization>().Fetch(authorization => authorization.Application) |
|||
where authorization.Application != null && |
|||
authorization.Application.Id.Equals(key) |
|||
select authorization).AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return authorization; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves an authorization using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the authorization.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the authorization corresponding to the identifier.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<TAuthorization> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
return await session.GetAsync<TAuthorization>(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>The authorizations corresponding to the specified subject.</returns>
|
|||
public virtual IAsyncEnumerable<TAuthorization> FindBySubjectAsync( |
|||
[NotNull] string subject, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(subject)) |
|||
{ |
|||
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TAuthorization> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
await foreach (var authorization in |
|||
(from authorization in session.Query<TAuthorization>().Fetch(authorization => authorization.Application) |
|||
where authorization.Subject == subject |
|||
select authorization).AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return authorization; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <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>(result: null); |
|||
} |
|||
|
|||
return new ValueTask<string>(ConvertIdentifierToString(authorization.Application.Id)); |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the first element returned when executing the query.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<TResult> GetAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken) |
|||
{ |
|||
if (query == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(query)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
return await query(session.Query<TAuthorization>() |
|||
.Fetch(authorization => authorization.Application), state).FirstOrDefaultAsync(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<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(authorization.Properties)) |
|||
{ |
|||
return new ValueTask<ImmutableDictionary<string, JsonElement>>(ImmutableDictionary.Create<string, JsonElement>()); |
|||
} |
|||
|
|||
// Note: parsing the stringified properties is an expensive operation.
|
|||
// To mitigate that, the resulting object is stored in the memory cache.
|
|||
var key = string.Concat("68056e1a-dbcf-412b-9a6a-d791c7dbe726", "\x1e", authorization.Properties); |
|||
var properties = Cache.GetOrCreate(key, entry => |
|||
{ |
|||
entry.SetPriority(CacheItemPriority.High) |
|||
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); |
|||
|
|||
return JsonSerializer.Deserialize<ImmutableDictionary<string, JsonElement>>(authorization.Properties); |
|||
}); |
|||
|
|||
return new ValueTask<ImmutableDictionary<string, JsonElement>>(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>()); |
|||
} |
|||
|
|||
// Note: parsing the stringified scopes is an expensive operation.
|
|||
// To mitigate that, the resulting array is stored in the memory cache.
|
|||
var key = string.Concat("2ba4ab0f-e2ec-4d48-b3bd-28e2bb660c75", "\x1e", authorization.Scopes); |
|||
var scopes = Cache.GetOrCreate(key, entry => |
|||
{ |
|||
entry.SetPriority(CacheItemPriority.High) |
|||
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); |
|||
|
|||
return JsonSerializer.Deserialize<ImmutableArray<string>>(authorization.Scopes); |
|||
}); |
|||
|
|||
return new ValueTask<ImmutableArray<string>>(scopes); |
|||
} |
|||
|
|||
/// <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) |
|||
{ |
|||
try |
|||
{ |
|||
return new ValueTask<TAuthorization>(Activator.CreateInstance<TAuthorization>()); |
|||
} |
|||
|
|||
catch (MemberAccessException exception) |
|||
{ |
|||
return new ValueTask<TAuthorization>(Task.FromException<TAuthorization>( |
|||
new InvalidOperationException(new StringBuilder() |
|||
.AppendLine("An error occurred while trying to create a new authorization instance.") |
|||
.Append("Make sure that the authorization entity is not abstract and has a public parameterless constructor ") |
|||
.Append("or create a custom authorization store that overrides 'InstantiateAsync()' to use a custom factory.") |
|||
.ToString(), exception))); |
|||
} |
|||
} |
|||
|
|||
/// <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>All the elements returned when executing the specified query.</returns>
|
|||
public virtual async IAsyncEnumerable<TAuthorization> ListAsync( |
|||
[CanBeNull] int? count, [CanBeNull] int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
var query = session.Query<TAuthorization>() |
|||
.Fetch(authorization => authorization.Application) |
|||
.OrderBy(authorization => authorization.Id) |
|||
.AsQueryable(); |
|||
|
|||
if (offset.HasValue) |
|||
{ |
|||
query = query.Skip(offset.Value); |
|||
} |
|||
|
|||
if (count.HasValue) |
|||
{ |
|||
query = query.Take(count.Value); |
|||
} |
|||
|
|||
await foreach (var authorization in query.AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return authorization; |
|||
} |
|||
} |
|||
|
|||
/// <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>All the elements returned when executing the specified query.</returns>
|
|||
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken) |
|||
{ |
|||
if (query == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(query)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TResult> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
await foreach (var element in query( |
|||
session.Query<TAuthorization>() |
|||
.Fetch(authorization => authorization.Application), state).AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return element; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the authorizations that are marked as invalid and the ad-hoc ones that have no valid/nonexpired token attached.
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async ValueTask PruneAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
await (from token in session.Query<TToken>() |
|||
where token.Status != OpenIddictConstants.Statuses.Valid || |
|||
token.ExpirationDate < DateTimeOffset.UtcNow |
|||
select token).DeleteAsync(cancellationToken); |
|||
|
|||
await (from authorization in session.Query<TAuthorization>() |
|||
where authorization.Status != OpenIddictConstants.Statuses.Valid || |
|||
(authorization.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && !authorization.Tokens.Any()) |
|||
select authorization).DeleteAsync(cancellationToken); |
|||
|
|||
await session.FlushAsync(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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async ValueTask SetApplicationIdAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
if (!string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
authorization.Application = await session.LoadAsync<TApplication>(ConvertIdentifierFromString(identifier), cancellationToken); |
|||
} |
|||
|
|||
else |
|||
{ |
|||
authorization.Application = null; |
|||
} |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetPropertiesAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (properties == null || properties.IsEmpty) |
|||
{ |
|||
authorization.Properties = null; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
authorization.Properties = JsonSerializer.Serialize(properties, new JsonSerializerOptions |
|||
{ |
|||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, |
|||
WriteIndented = false |
|||
}); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetScopesAsync([NotNull] TAuthorization authorization, |
|||
ImmutableArray<string> scopes, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
if (scopes.IsDefaultOrEmpty) |
|||
{ |
|||
authorization.Scopes = null; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
authorization.Scopes = JsonSerializer.Serialize(scopes, new JsonSerializerOptions |
|||
{ |
|||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, |
|||
WriteIndented = false |
|||
}); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetStatusAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] string status, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
authorization.Status = status; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetSubjectAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] string subject, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
authorization.Subject = subject; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetTypeAsync([NotNull] TAuthorization authorization, |
|||
[CanBeNull] string type, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
authorization.Type = type; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async ValueTask UpdateAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) |
|||
{ |
|||
if (authorization == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(authorization)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
try |
|||
{ |
|||
await session.UpdateAsync(authorization, cancellationToken); |
|||
await session.FlushAsync(cancellationToken); |
|||
} |
|||
|
|||
catch (StaleObjectStateException exception) |
|||
{ |
|||
throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() |
|||
.AppendLine("The authorization was concurrently updated and cannot be persisted in its current state.") |
|||
.Append("Reload the authorization from the database and retry the operation.") |
|||
.ToString(), exception); |
|||
} |
|||
} |
|||
|
|||
/// <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,720 +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.Generic; |
|||
using System.Collections.Immutable; |
|||
using System.ComponentModel; |
|||
using System.Linq; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Text; |
|||
using System.Text.Encodings.Web; |
|||
using System.Text.Json; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.Options; |
|||
using NHibernate; |
|||
using NHibernate.Cfg; |
|||
using NHibernate.Linq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.NHibernate.Models; |
|||
|
|||
namespace OpenIddict.NHibernate |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the scopes stored in a database.
|
|||
/// </summary>
|
|||
public class OpenIddictScopeStore : OpenIddictScopeStore<OpenIddictScope, string> |
|||
{ |
|||
public OpenIddictScopeStore( |
|||
[NotNull] IMemoryCache cache, |
|||
[NotNull] IOpenIddictNHibernateContext context, |
|||
[NotNull] IOptionsMonitor<OpenIddictNHibernateOptions> options) |
|||
: base(cache, context, options) |
|||
{ |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the scopes stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public class OpenIddictScopeStore<TKey> : OpenIddictScopeStore<OpenIddictScope<TKey>, TKey> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
public OpenIddictScopeStore( |
|||
[NotNull] IMemoryCache cache, |
|||
[NotNull] IOpenIddictNHibernateContext context, |
|||
[NotNull] IOptionsMonitor<OpenIddictNHibernateOptions> options) |
|||
: base(cache, context, options) |
|||
{ |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Provides methods allowing to manage the scopes stored in a database.
|
|||
/// </summary>
|
|||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|||
/// <typeparam name="TKey">The type of the entity primary keys.</typeparam>
|
|||
public class OpenIddictScopeStore<TScope, TKey> : IOpenIddictScopeStore<TScope> |
|||
where TScope : OpenIddictScope<TKey> |
|||
where TKey : IEquatable<TKey> |
|||
{ |
|||
public OpenIddictScopeStore( |
|||
[NotNull] IMemoryCache cache, |
|||
[NotNull] IOpenIddictNHibernateContext context, |
|||
[NotNull] IOptionsMonitor<OpenIddictNHibernateOptions> options) |
|||
{ |
|||
Cache = cache; |
|||
Context = context; |
|||
Options = options; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the memory cache associated with the current store.
|
|||
/// </summary>
|
|||
protected IMemoryCache Cache { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the database context associated with the current store.
|
|||
/// </summary>
|
|||
protected IOpenIddictNHibernateContext Context { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the options associated with the current store.
|
|||
/// </summary>
|
|||
protected IOptionsMonitor<OpenIddictNHibernateOptions> Options { 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="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of scopes in the database.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<long> CountAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
return await session.Query<TScope>().LongCountAsync(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="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the number of scopes that match the specified query.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<long> CountAsync<TResult>([NotNull] Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken) |
|||
{ |
|||
if (query == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(query)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
return await query(session.Query<TScope>()).LongCountAsync(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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async ValueTask CreateAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
await session.SaveAsync(scope, cancellationToken); |
|||
await session.FlushAsync(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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async ValueTask DeleteAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
try |
|||
{ |
|||
await session.DeleteAsync(scope, cancellationToken); |
|||
await session.FlushAsync(cancellationToken); |
|||
} |
|||
|
|||
catch (StaleObjectStateException exception) |
|||
{ |
|||
throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() |
|||
.AppendLine("The scope was concurrently updated and cannot be persisted in its current state.") |
|||
.Append("Reload the scope from the database and retry the operation.") |
|||
.ToString(), exception); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves a scope using its unique identifier.
|
|||
/// </summary>
|
|||
/// <param name="identifier">The unique identifier associated with the scope.</param>
|
|||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scope corresponding to the identifier.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<TScope> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(identifier)) |
|||
{ |
|||
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
return await session.GetAsync<TScope>(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="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the scope corresponding to the specified name.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<TScope> FindByNameAsync([NotNull] string name, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(name)) |
|||
{ |
|||
throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
return await (from scope in session.Query<TScope>() |
|||
where scope.Name == name |
|||
select scope).FirstOrDefaultAsync(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>The scopes corresponding to the specified names.</returns>
|
|||
public virtual IAsyncEnumerable<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)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TScope> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
// Note: Enumerable.Contains() is deliberately used without the extension method syntax to ensure
|
|||
// ImmutableArray.Contains() (which is not fully supported by NHibernate) is not used instead.
|
|||
await foreach (var scope in (from scope in session.Query<TScope>() |
|||
where Enumerable.Contains(names, scope.Name) |
|||
select scope).AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return scope; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <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>The scopes associated with the specified resource.</returns>
|
|||
public virtual IAsyncEnumerable<TScope> FindByResourceAsync([NotNull] string resource, CancellationToken cancellationToken) |
|||
{ |
|||
if (string.IsNullOrEmpty(resource)) |
|||
{ |
|||
throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TScope> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
// 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.
|
|||
await foreach (var scope in session.Query<TScope>() |
|||
.Where(scope => scope.Resources.Contains(resource)) |
|||
.AsAsyncEnumerable(cancellationToken) |
|||
.WhereAwait(async scope => (await GetResourcesAsync(scope, cancellationToken)).Contains(resource, StringComparer.Ordinal))) |
|||
{ |
|||
yield return scope; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation,
|
|||
/// whose result returns the first element returned when executing the query.
|
|||
/// </returns>
|
|||
public virtual async ValueTask<TResult> GetAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TScope>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken) |
|||
{ |
|||
if (query == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(query)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
return await query(session.Query<TScope>(), state).FirstOrDefaultAsync(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<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(scope.Properties)) |
|||
{ |
|||
return new ValueTask<ImmutableDictionary<string, JsonElement>>(ImmutableDictionary.Create<string, JsonElement>()); |
|||
} |
|||
|
|||
// Note: parsing the stringified properties is an expensive operation.
|
|||
// To mitigate that, the resulting object is stored in the memory cache.
|
|||
var key = string.Concat("78d8dfdd-3870-442e-b62e-dc9bf6eaeff7", "\x1e", scope.Properties); |
|||
var properties = Cache.GetOrCreate(key, entry => |
|||
{ |
|||
entry.SetPriority(CacheItemPriority.High) |
|||
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); |
|||
|
|||
return JsonSerializer.Deserialize<ImmutableDictionary<string, JsonElement>>(scope.Properties); |
|||
}); |
|||
|
|||
return new ValueTask<ImmutableDictionary<string, JsonElement>>(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 JsonSerializer.Deserialize<ImmutableArray<string>>(scope.Resources); |
|||
}); |
|||
|
|||
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) |
|||
{ |
|||
try |
|||
{ |
|||
return new ValueTask<TScope>(Activator.CreateInstance<TScope>()); |
|||
} |
|||
|
|||
catch (MemberAccessException exception) |
|||
{ |
|||
return new ValueTask<TScope>(Task.FromException<TScope>( |
|||
new InvalidOperationException(new StringBuilder() |
|||
.AppendLine("An error occurred while trying to create a new scope instance.") |
|||
.Append("Make sure that the scope entity is not abstract and has a public parameterless constructor ") |
|||
.Append("or create a custom scope store that overrides 'InstantiateAsync()' to use a custom factory.") |
|||
.ToString(), exception))); |
|||
} |
|||
} |
|||
|
|||
/// <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>All the elements returned when executing the specified query.</returns>
|
|||
public virtual async IAsyncEnumerable<TScope> ListAsync( |
|||
[CanBeNull] int? count, [CanBeNull] int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
var query = session.Query<TScope>() |
|||
.OrderBy(scope => scope.Id) |
|||
.AsQueryable(); |
|||
|
|||
if (offset.HasValue) |
|||
{ |
|||
query = query.Skip(offset.Value); |
|||
} |
|||
|
|||
if (count.HasValue) |
|||
{ |
|||
query = query.Take(count.Value); |
|||
} |
|||
|
|||
await foreach (var scope in query.AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return scope; |
|||
} |
|||
} |
|||
|
|||
/// <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>All the elements returned when executing the specified query.</returns>
|
|||
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>( |
|||
[NotNull] Func<IQueryable<TScope>, TState, IQueryable<TResult>> query, |
|||
[CanBeNull] TState state, CancellationToken cancellationToken) |
|||
{ |
|||
if (query == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(query)); |
|||
} |
|||
|
|||
return ExecuteAsync(cancellationToken); |
|||
|
|||
async IAsyncEnumerable<TResult> ExecuteAsync(CancellationToken cancellationToken) |
|||
{ |
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
await foreach (var element in query(session.Query<TScope>(), state).AsAsyncEnumerable(cancellationToken)) |
|||
{ |
|||
yield return element; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetDescriptionAsync([NotNull] TScope scope, [CanBeNull] string description, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
scope.Description = description; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetDisplayNameAsync([NotNull] TScope scope, [CanBeNull] string name, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
scope.DisplayName = name; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetNameAsync([NotNull] TScope scope, [CanBeNull] string name, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
scope.Name = name; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetPropertiesAsync([NotNull] TScope scope, |
|||
[CanBeNull] ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
if (properties == null || properties.IsEmpty) |
|||
{ |
|||
scope.Properties = null; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
scope.Properties = JsonSerializer.Serialize(properties, new JsonSerializerOptions |
|||
{ |
|||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, |
|||
WriteIndented = false |
|||
}); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual ValueTask SetResourcesAsync([NotNull] TScope scope, ImmutableArray<string> resources, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
if (resources.IsDefaultOrEmpty) |
|||
{ |
|||
scope.Resources = null; |
|||
|
|||
return default; |
|||
} |
|||
|
|||
scope.Resources = JsonSerializer.Serialize(resources, new JsonSerializerOptions |
|||
{ |
|||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, |
|||
WriteIndented = false |
|||
}); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
/// <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="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
|
|||
public virtual async ValueTask UpdateAsync([NotNull] TScope scope, CancellationToken cancellationToken) |
|||
{ |
|||
if (scope == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(scope)); |
|||
} |
|||
|
|||
var session = await Context.GetSessionAsync(cancellationToken); |
|||
|
|||
try |
|||
{ |
|||
await session.UpdateAsync(scope, cancellationToken); |
|||
await session.FlushAsync(cancellationToken); |
|||
} |
|||
|
|||
catch (StaleObjectStateException exception) |
|||
{ |
|||
throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() |
|||
.AppendLine("The scope was concurrently updated and cannot be persisted in its current state.") |
|||
.Append("Reload the scope from the database and retry the operation.") |
|||
.ToString(), exception); |
|||
} |
|||
} |
|||
|
|||
/// <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); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -1,16 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFrameworks>net461;netcoreapp2.1;netcoreapp3.0</TargetFrameworks> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\OpenIddict.NHibernate\OpenIddict.NHibernate.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(ExtensionsVersion)" /> |
|||
<PackageReference Include="Moq" Version="$(MoqVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,122 +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.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Moq; |
|||
using NHibernate; |
|||
using OpenIddict.Core; |
|||
using OpenIddict.NHibernate.Models; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.NHibernate.Tests |
|||
{ |
|||
public class OpenIddictNHibernateBuilderTests |
|||
{ |
|||
[Fact] |
|||
public void Constructor_ThrowsAnExceptionForNullServices() |
|||
{ |
|||
// Arrange
|
|||
var services = (IServiceCollection) null; |
|||
|
|||
// Act and assert
|
|||
var exception = Assert.Throws<ArgumentNullException>(() => new OpenIddictNHibernateBuilder(services)); |
|||
|
|||
Assert.Equal("services", exception.ParamName); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ReplaceDefaultEntities_EntitiesAreCorrectlyReplaced() |
|||
{ |
|||
// Arrange
|
|||
var services = CreateServices(); |
|||
var builder = CreateBuilder(services); |
|||
|
|||
// Act
|
|||
builder.ReplaceDefaultEntities<CustomApplication, CustomAuthorization, CustomScope, CustomToken, long>(); |
|||
|
|||
// Assert
|
|||
var provider = services.BuildServiceProvider(); |
|||
var options = provider.GetRequiredService<IOptionsMonitor<OpenIddictCoreOptions>>().CurrentValue; |
|||
|
|||
Assert.Equal(typeof(CustomApplication), options.DefaultApplicationType); |
|||
Assert.Equal(typeof(CustomAuthorization), options.DefaultAuthorizationType); |
|||
Assert.Equal(typeof(CustomScope), options.DefaultScopeType); |
|||
Assert.Equal(typeof(CustomToken), options.DefaultTokenType); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ReplaceDefaultEntities_AllowsSpecifyingCustomKeyType() |
|||
{ |
|||
// Arrange
|
|||
var services = CreateServices(); |
|||
var builder = CreateBuilder(services); |
|||
|
|||
// Act
|
|||
builder.ReplaceDefaultEntities<long>(); |
|||
|
|||
// Assert
|
|||
var provider = services.BuildServiceProvider(); |
|||
var options = provider.GetRequiredService<IOptionsMonitor<OpenIddictCoreOptions>>().CurrentValue; |
|||
|
|||
Assert.Equal(typeof(OpenIddictApplication<long>), options.DefaultApplicationType); |
|||
Assert.Equal(typeof(OpenIddictAuthorization<long>), options.DefaultAuthorizationType); |
|||
Assert.Equal(typeof(OpenIddictScope<long>), options.DefaultScopeType); |
|||
Assert.Equal(typeof(OpenIddictToken<long>), options.DefaultTokenType); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UseSessionFactory_ThrowsAnExceptionForNullFactory() |
|||
{ |
|||
// Arrange
|
|||
var services = CreateServices(); |
|||
var builder = CreateBuilder(services); |
|||
|
|||
// Act and assert
|
|||
var exception = Assert.Throws<ArgumentNullException>(delegate |
|||
{ |
|||
return builder.UseSessionFactory(factory: null); |
|||
}); |
|||
|
|||
Assert.Equal("factory", exception.ParamName); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UseSessionFactory_SetsDbContextTypeInOptions() |
|||
{ |
|||
// Arrange
|
|||
var services = CreateServices(); |
|||
var builder = CreateBuilder(services); |
|||
var factory = Mock.Of<ISessionFactory>(); |
|||
|
|||
// Act
|
|||
builder.UseSessionFactory(factory); |
|||
|
|||
// Assert
|
|||
var provider = services.BuildServiceProvider(); |
|||
var options = provider.GetRequiredService<IOptionsMonitor<OpenIddictNHibernateOptions>>().CurrentValue; |
|||
|
|||
Assert.Same(factory, options.SessionFactory); |
|||
} |
|||
|
|||
private static OpenIddictNHibernateBuilder CreateBuilder(IServiceCollection services) |
|||
=> services.AddOpenIddict().AddCore().UseNHibernate(); |
|||
|
|||
private static IServiceCollection CreateServices() |
|||
{ |
|||
var services = new ServiceCollection(); |
|||
services.AddOptions(); |
|||
|
|||
return services; |
|||
} |
|||
|
|||
public class CustomApplication : OpenIddictApplication<long, CustomAuthorization, CustomToken> { } |
|||
public class CustomAuthorization : OpenIddictAuthorization<long, CustomApplication, CustomToken> { } |
|||
public class CustomScope : OpenIddictScope<long> { } |
|||
public class CustomToken : OpenIddictToken<long, CustomApplication, CustomAuthorization> { } |
|||
} |
|||
} |
|||
@ -1,240 +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.Text; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Moq; |
|||
using NHibernate; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.NHibernate.Tests |
|||
{ |
|||
public class OpenIddictNHibernateContextTests |
|||
{ |
|||
[Fact] |
|||
public async Task GetSessionAsync_ThrowsAnExceptionForCanceledToken() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var provider = services.BuildServiceProvider(); |
|||
|
|||
var options = Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>(); |
|||
var token = new CancellationToken(canceled: true); |
|||
|
|||
var context = new OpenIddictNHibernateContext(options, provider); |
|||
|
|||
// Act and assert
|
|||
var exception = await Assert.ThrowsAsync<TaskCanceledException>(async delegate |
|||
{ |
|||
await context.GetSessionAsync(token); |
|||
}); |
|||
|
|||
Assert.Equal(token, exception.CancellationToken); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetSessionAsync_UsesSessionRegisteredInDependencyInjectionContainer() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
|
|||
var session = new Mock<ISession>(); |
|||
var factory = new Mock<ISessionFactory>(); |
|||
|
|||
services.AddSingleton(session.Object); |
|||
services.AddSingleton(factory.Object); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
|
|||
var options = Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>( |
|||
mock => mock.CurrentValue == new OpenIddictNHibernateOptions |
|||
{ |
|||
SessionFactory = null |
|||
}); |
|||
|
|||
var context = new OpenIddictNHibernateContext(options, provider); |
|||
|
|||
// Act and assert
|
|||
Assert.Same(session.Object, await context.GetSessionAsync(CancellationToken.None)); |
|||
factory.Verify(mock => mock.OpenSession(), Times.Never()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(FlushMode.Always)] |
|||
[InlineData(FlushMode.Auto)] |
|||
[InlineData(FlushMode.Commit)] |
|||
[InlineData(FlushMode.Unspecified)] |
|||
public async Task GetSessionAsync_CreatesSubSessionWhenFlushModeIsNotManual(FlushMode mode) |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
|
|||
var session = new Mock<ISession>(); |
|||
session.SetupProperty(mock => mock.FlushMode, mode); |
|||
|
|||
var builder = new Mock<ISharedSessionBuilder>(); |
|||
builder.Setup(mock => mock.AutoClose()) |
|||
.Returns(builder.Object); |
|||
builder.Setup(mock => mock.AutoJoinTransaction()) |
|||
.Returns(builder.Object); |
|||
builder.Setup(mock => mock.Connection()) |
|||
.Returns(builder.Object); |
|||
builder.Setup(mock => mock.ConnectionReleaseMode()) |
|||
.Returns(builder.Object); |
|||
builder.Setup(mock => mock.FlushMode(FlushMode.Manual)) |
|||
.Returns(builder.Object); |
|||
builder.Setup(mock => mock.Interceptor()) |
|||
.Returns(builder.Object); |
|||
builder.Setup(mock => mock.OpenSession()) |
|||
.Returns(session.Object); |
|||
|
|||
session.Setup(mock => mock.SessionWithOptions()) |
|||
.Returns(builder.Object); |
|||
|
|||
var factory = new Mock<ISessionFactory>(); |
|||
|
|||
services.AddSingleton(session.Object); |
|||
services.AddSingleton(factory.Object); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
|
|||
var options = Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>( |
|||
mock => mock.CurrentValue == new OpenIddictNHibernateOptions |
|||
{ |
|||
SessionFactory = null |
|||
}); |
|||
|
|||
var context = new OpenIddictNHibernateContext(options, provider); |
|||
|
|||
// Act and assert
|
|||
Assert.Same(session.Object, await context.GetSessionAsync(CancellationToken.None)); |
|||
builder.Verify(mock => mock.AutoClose(), Times.Once()); |
|||
builder.Verify(mock => mock.AutoJoinTransaction(), Times.Once()); |
|||
builder.Verify(mock => mock.Connection(), Times.Once()); |
|||
builder.Verify(mock => mock.ConnectionReleaseMode(), Times.Once()); |
|||
builder.Verify(mock => mock.FlushMode(FlushMode.Manual), Times.Once()); |
|||
builder.Verify(mock => mock.Interceptor(), Times.Once()); |
|||
builder.Verify(mock => mock.OpenSession(), Times.Once()); |
|||
factory.Verify(mock => mock.OpenSession(), Times.Never()); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetSessionAsync_UsesSessionFactoryRegisteredInDependencyInjectionContainer() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<ISessionFactory>()); |
|||
|
|||
var session = new Mock<ISession>(); |
|||
var factory = new Mock<ISessionFactory>(); |
|||
factory.Setup(mock => mock.OpenSession()) |
|||
.Returns(session.Object); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
|
|||
var options = Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>( |
|||
mock => mock.CurrentValue == new OpenIddictNHibernateOptions |
|||
{ |
|||
SessionFactory = factory.Object |
|||
}); |
|||
|
|||
var context = new OpenIddictNHibernateContext(options, provider); |
|||
|
|||
// Act and assert
|
|||
Assert.Same(session.Object, await context.GetSessionAsync(CancellationToken.None)); |
|||
factory.Verify(mock => mock.OpenSession(), Times.Once()); |
|||
session.VerifySet(mock => mock.FlushMode = FlushMode.Manual, Times.Once()); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetSessionAsync_ThrowsAnExceptionWhenSessionFactoryCannotBeFound() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var provider = services.BuildServiceProvider(); |
|||
|
|||
var options = Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>( |
|||
mock => mock.CurrentValue == new OpenIddictNHibernateOptions |
|||
{ |
|||
SessionFactory = null |
|||
}); |
|||
|
|||
var context = new OpenIddictNHibernateContext(options, provider); |
|||
|
|||
// Act and assert
|
|||
var exception = await Assert.ThrowsAsync<InvalidOperationException>(async delegate |
|||
{ |
|||
await context.GetSessionAsync(CancellationToken.None); |
|||
}); |
|||
|
|||
Assert.Equal(new StringBuilder() |
|||
.AppendLine("No suitable NHibernate session or session factory can be found.") |
|||
.Append("To configure the OpenIddict NHibernate stores to use a specific factory, use ") |
|||
.Append("'services.AddOpenIddict().AddCore().UseNHibernate().UseSessionFactory()' or register an ") |
|||
.Append("'ISession'/'ISessionFactory' in the dependency injection container in 'ConfigureServices()'.") |
|||
.ToString(), exception.Message); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetSessionAsync_PrefersSessionFactoryRegisteredInOptionsToSessionRegisteredInDependencyInjectionContainer() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<ISessionFactory>()); |
|||
|
|||
var session = new Mock<ISession>(); |
|||
var factory = new Mock<ISessionFactory>(); |
|||
factory.Setup(mock => mock.OpenSession()) |
|||
.Returns(session.Object); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
|
|||
var options = Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>( |
|||
mock => mock.CurrentValue == new OpenIddictNHibernateOptions |
|||
{ |
|||
SessionFactory = factory.Object |
|||
}); |
|||
|
|||
var context = new OpenIddictNHibernateContext(options, provider); |
|||
|
|||
// Act and assert
|
|||
Assert.Same(session.Object, await context.GetSessionAsync(CancellationToken.None)); |
|||
factory.Verify(mock => mock.OpenSession(), Times.Once()); |
|||
session.VerifySet(mock => mock.FlushMode = FlushMode.Manual, Times.Once()); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetSessionAsync_ReturnsCachedSession() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var provider = services.BuildServiceProvider(); |
|||
|
|||
var factory = new Mock<ISessionFactory>(); |
|||
factory.Setup(mock => mock.OpenSession()) |
|||
.Returns(() => Mock.Of<ISession>()); |
|||
|
|||
var options = Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>( |
|||
mock => mock.CurrentValue == new OpenIddictNHibernateOptions |
|||
{ |
|||
SessionFactory = factory.Object |
|||
}); |
|||
|
|||
var context = new OpenIddictNHibernateContext(options, provider); |
|||
|
|||
// Act and assert
|
|||
Assert.Same( |
|||
await context.GetSessionAsync(CancellationToken.None), |
|||
await context.GetSessionAsync(CancellationToken.None)); |
|||
|
|||
factory.Verify(mock => mock.OpenSession(), Times.Once()); |
|||
} |
|||
} |
|||
} |
|||
@ -1,120 +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.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.Core; |
|||
using OpenIddict.NHibernate.Models; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.NHibernate.Tests |
|||
{ |
|||
public class OpenIddictNHibernateExtensionsTests |
|||
{ |
|||
[Fact] |
|||
public void UseNHibernate_ThrowsAnExceptionForNullBuilder() |
|||
{ |
|||
// Arrange
|
|||
var builder = (OpenIddictCoreBuilder) null; |
|||
|
|||
// Act and assert
|
|||
var exception = Assert.Throws<ArgumentNullException>(() => builder.UseNHibernate()); |
|||
|
|||
Assert.Equal("builder", exception.ParamName); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UseNHibernate_ThrowsAnExceptionForNullConfiguration() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var builder = new OpenIddictCoreBuilder(services); |
|||
|
|||
// Act and assert
|
|||
var exception = Assert.Throws<ArgumentNullException>(() => builder.UseNHibernate(configuration: null)); |
|||
|
|||
Assert.Equal("configuration", exception.ParamName); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UseNHibernate_RegistersDefaultEntities() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection().AddOptions(); |
|||
var builder = new OpenIddictCoreBuilder(services); |
|||
|
|||
// Act
|
|||
builder.UseNHibernate(); |
|||
|
|||
// 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); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(typeof(IOpenIddictApplicationStoreResolver), typeof(OpenIddictApplicationStoreResolver))] |
|||
[InlineData(typeof(IOpenIddictAuthorizationStoreResolver), typeof(OpenIddictAuthorizationStoreResolver))] |
|||
[InlineData(typeof(IOpenIddictScopeStoreResolver), typeof(OpenIddictScopeStoreResolver))] |
|||
[InlineData(typeof(IOpenIddictTokenStoreResolver), typeof(OpenIddictTokenStoreResolver))] |
|||
public void UseNHibernate_RegistersNHibernateStoreResolvers(Type serviceType, Type implementationType) |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var builder = new OpenIddictCoreBuilder(services); |
|||
|
|||
// Act
|
|||
builder.UseNHibernate(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(services, service => service.ServiceType == serviceType && |
|||
service.ImplementationType == implementationType); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(typeof(OpenIddictApplicationStoreResolver.TypeResolutionCache))] |
|||
[InlineData(typeof(OpenIddictAuthorizationStoreResolver.TypeResolutionCache))] |
|||
[InlineData(typeof(OpenIddictScopeStoreResolver.TypeResolutionCache))] |
|||
[InlineData(typeof(OpenIddictTokenStoreResolver.TypeResolutionCache))] |
|||
public void UseEntityFramework_RegistersNHibernateStoreResolverCaches(Type type) |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var builder = new OpenIddictCoreBuilder(services); |
|||
|
|||
// Act
|
|||
builder.UseNHibernate(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(services, service => service.ServiceType == type && |
|||
service.ImplementationType == type); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(typeof(OpenIddictApplicationStore<,,,>))] |
|||
[InlineData(typeof(OpenIddictAuthorizationStore<,,,>))] |
|||
[InlineData(typeof(OpenIddictScopeStore<,>))] |
|||
[InlineData(typeof(OpenIddictTokenStore<,,,>))] |
|||
public void UseNHibernate_RegistersNHibernateStore(Type type) |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
var builder = new OpenIddictCoreBuilder(services); |
|||
|
|||
// Act
|
|||
builder.UseNHibernate(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(services, service => service.ServiceType == type && service.ImplementationType == type); |
|||
} |
|||
} |
|||
} |
|||
@ -1,84 +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.Text; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Moq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.NHibernate.Models; |
|||
using Xunit; |
|||
using static OpenIddict.NHibernate.OpenIddictApplicationStoreResolver; |
|||
|
|||
namespace OpenIddict.NHibernate.Tests |
|||
{ |
|||
public class OpenIddictApplicationStoreResolverTests |
|||
{ |
|||
[Fact] |
|||
public void Get_ReturnsCustomStoreCorrespondingToTheSpecifiedTypeWhenAvailable() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<IOpenIddictApplicationStore<CustomApplication>>()); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictApplicationStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull(resolver.Get<CustomApplication>()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get_ThrowsAnExceptionForInvalidEntityType() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictApplicationStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
var exception = Assert.Throws<InvalidOperationException>(() => resolver.Get<CustomApplication>()); |
|||
|
|||
Assert.Equal(new StringBuilder() |
|||
.AppendLine("The specified application type is not compatible with the NHibernate stores.") |
|||
.Append("When enabling the NHibernate stores, make sure you use the built-in ") |
|||
.Append("'OpenIddictApplication' entity (from the 'OpenIddict.NHibernate.Models' package) ") |
|||
.Append("or a custom entity that inherits from the generic 'OpenIddictApplication' entity.") |
|||
.ToString(), exception.Message); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get_ReturnsDefaultStoreCorrespondingToTheSpecifiedTypeWhenAvailable() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<IOpenIddictApplicationStore<CustomApplication>>()); |
|||
services.AddSingleton(CreateStore()); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictApplicationStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull(resolver.Get<MyApplication>()); |
|||
} |
|||
|
|||
private static OpenIddictApplicationStore<MyApplication, MyAuthorization, MyToken, long> CreateStore() |
|||
=> new Mock<OpenIddictApplicationStore<MyApplication, MyAuthorization, MyToken, long>>( |
|||
Mock.Of<IMemoryCache>(), |
|||
Mock.Of<IOpenIddictNHibernateContext>(), |
|||
Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>()).Object; |
|||
|
|||
public class CustomApplication { } |
|||
|
|||
public class MyApplication : OpenIddictApplication<long, MyAuthorization, MyToken> { } |
|||
public class MyAuthorization : OpenIddictAuthorization<long, MyApplication, MyToken> { } |
|||
public class MyScope : OpenIddictScope<long> { } |
|||
public class MyToken : OpenIddictToken<long, MyApplication, MyAuthorization> { } |
|||
} |
|||
} |
|||
@ -1,84 +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.Text; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Moq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.NHibernate.Models; |
|||
using Xunit; |
|||
using static OpenIddict.NHibernate.OpenIddictAuthorizationStoreResolver; |
|||
|
|||
namespace OpenIddict.NHibernate.Tests |
|||
{ |
|||
public class OpenIddictAuthorizationStoreResolverTests |
|||
{ |
|||
[Fact] |
|||
public void Get_ReturnsCustomStoreCorrespondingToTheSpecifiedTypeWhenAvailable() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<IOpenIddictAuthorizationStore<CustomAuthorization>>()); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictAuthorizationStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull(resolver.Get<CustomAuthorization>()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get_ThrowsAnExceptionForInvalidEntityType() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictAuthorizationStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
var exception = Assert.Throws<InvalidOperationException>(() => resolver.Get<CustomAuthorization>()); |
|||
|
|||
Assert.Equal(new StringBuilder() |
|||
.AppendLine("The specified authorization type is not compatible with the NHibernate stores.") |
|||
.Append("When enabling the NHibernate stores, make sure you use the built-in ") |
|||
.Append("'OpenIddictAuthorization' entity (from the 'OpenIddict.NHibernate.Models' package) ") |
|||
.Append("or a custom entity that inherits from the generic 'OpenIddictAuthorization' entity.") |
|||
.ToString(), exception.Message); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get_ReturnsDefaultStoreCorrespondingToTheSpecifiedTypeWhenAvailable() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<IOpenIddictAuthorizationStore<CustomAuthorization>>()); |
|||
services.AddSingleton(CreateStore()); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictAuthorizationStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull(resolver.Get<MyAuthorization>()); |
|||
} |
|||
|
|||
private static OpenIddictAuthorizationStore<MyAuthorization, MyApplication, MyToken, long> CreateStore() |
|||
=> new Mock<OpenIddictAuthorizationStore<MyAuthorization, MyApplication, MyToken, long>>( |
|||
Mock.Of<IMemoryCache>(), |
|||
Mock.Of<IOpenIddictNHibernateContext>(), |
|||
Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>()).Object; |
|||
|
|||
public class CustomAuthorization { } |
|||
|
|||
public class MyApplication : OpenIddictApplication<long, MyAuthorization, MyToken> { } |
|||
public class MyAuthorization : OpenIddictAuthorization<long, MyApplication, MyToken> { } |
|||
public class MyScope : OpenIddictScope<long> { } |
|||
public class MyToken : OpenIddictToken<long, MyApplication, MyAuthorization> { } |
|||
} |
|||
} |
|||
@ -1,84 +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.Text; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Moq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.NHibernate.Models; |
|||
using Xunit; |
|||
using static OpenIddict.NHibernate.OpenIddictScopeStoreResolver; |
|||
|
|||
namespace OpenIddict.NHibernate.Tests |
|||
{ |
|||
public class OpenIddictScopeStoreResolverTests |
|||
{ |
|||
[Fact] |
|||
public void Get_ReturnsCustomStoreCorrespondingToTheSpecifiedTypeWhenAvailable() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<IOpenIddictScopeStore<CustomScope>>()); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictScopeStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull(resolver.Get<CustomScope>()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get_ThrowsAnExceptionForInvalidEntityType() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictScopeStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
var exception = Assert.Throws<InvalidOperationException>(() => resolver.Get<CustomScope>()); |
|||
|
|||
Assert.Equal(new StringBuilder() |
|||
.AppendLine("The specified scope type is not compatible with the NHibernate stores.") |
|||
.Append("When enabling the NHibernate stores, make sure you use the built-in ") |
|||
.Append("'OpenIddictScope' entity (from the 'OpenIddict.NHibernate.Models' package) ") |
|||
.Append("or a custom entity that inherits from the generic 'OpenIddictScope' entity.") |
|||
.ToString(), exception.Message); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get_ReturnsDefaultStoreCorrespondingToTheSpecifiedTypeWhenAvailable() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<IOpenIddictScopeStore<CustomScope>>()); |
|||
services.AddSingleton(CreateStore()); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictScopeStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull(resolver.Get<MyScope>()); |
|||
} |
|||
|
|||
private static OpenIddictScopeStore<MyScope, long> CreateStore() |
|||
=> new Mock<OpenIddictScopeStore<MyScope, long>>( |
|||
Mock.Of<IMemoryCache>(), |
|||
Mock.Of<IOpenIddictNHibernateContext>(), |
|||
Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>()).Object; |
|||
|
|||
public class CustomScope { } |
|||
|
|||
public class MyApplication : OpenIddictApplication<long, MyAuthorization, MyToken> { } |
|||
public class MyAuthorization : OpenIddictAuthorization<long, MyApplication, MyToken> { } |
|||
public class MyScope : OpenIddictScope<long> { } |
|||
public class MyToken : OpenIddictToken<long, MyApplication, MyAuthorization> { } |
|||
} |
|||
} |
|||
@ -1,84 +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.Text; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Moq; |
|||
using OpenIddict.Abstractions; |
|||
using OpenIddict.NHibernate.Models; |
|||
using Xunit; |
|||
using static OpenIddict.NHibernate.OpenIddictTokenStoreResolver; |
|||
|
|||
namespace OpenIddict.NHibernate.Tests |
|||
{ |
|||
public class OpenIddictTokenStoreResolverTests |
|||
{ |
|||
[Fact] |
|||
public void Get_ReturnsCustomStoreCorrespondingToTheSpecifiedTypeWhenAvailable() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<IOpenIddictTokenStore<CustomToken>>()); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictTokenStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull(resolver.Get<CustomToken>()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get_ThrowsAnExceptionForInvalidEntityType() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictTokenStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
var exception = Assert.Throws<InvalidOperationException>(() => resolver.Get<CustomToken>()); |
|||
|
|||
Assert.Equal(new StringBuilder() |
|||
.AppendLine("The specified token type is not compatible with the NHibernate stores.") |
|||
.Append("When enabling the NHibernate stores, make sure you use the built-in ") |
|||
.Append("'OpenIddictToken' entity (from the 'OpenIddict.NHibernate.Models' package) ") |
|||
.Append("or a custom entity that inherits from the generic 'OpenIddictToken' entity.") |
|||
.ToString(), exception.Message); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get_ReturnsDefaultStoreCorrespondingToTheSpecifiedTypeWhenAvailable() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddSingleton(Mock.Of<IOpenIddictTokenStore<CustomToken>>()); |
|||
services.AddSingleton(CreateStore()); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var resolver = new OpenIddictTokenStoreResolver(new TypeResolutionCache(), provider); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull(resolver.Get<MyToken>()); |
|||
} |
|||
|
|||
private static OpenIddictTokenStore<MyToken, MyApplication, MyAuthorization, long> CreateStore() |
|||
=> new Mock<OpenIddictTokenStore<MyToken, MyApplication, MyAuthorization, long>>( |
|||
Mock.Of<IMemoryCache>(), |
|||
Mock.Of<IOpenIddictNHibernateContext>(), |
|||
Mock.Of<IOptionsMonitor<OpenIddictNHibernateOptions>>()).Object; |
|||
|
|||
public class CustomToken { } |
|||
|
|||
public class MyApplication : OpenIddictApplication<long, MyAuthorization, MyToken> { } |
|||
public class MyAuthorization : OpenIddictAuthorization<long, MyApplication, MyToken> { } |
|||
public class MyScope : OpenIddictScope<long> { } |
|||
public class MyToken : OpenIddictToken<long, MyApplication, MyAuthorization> { } |
|||
} |
|||
} |
|||
Loading…
Reference in new issue