Browse Source

Backport the Entity Framework stores changes to OpenIddict 1.x

pull/553/head
Kévin Chalet 8 years ago
parent
commit
361641cbb4
  1. 7
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  2. 7
      src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs
  3. 20
      src/OpenIddict.Core/Stores/OpenIddictApplicationStore.cs
  4. 35
      src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
  5. 53
      src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
  6. 2
      src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
  7. 4
      src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs
  8. 42
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
  9. 68
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs

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

@ -173,16 +173,17 @@ namespace OpenIddict.Core
}
/// <summary>
/// Retrieves an authorization using its associated subject/client.
/// Retrieves the authorizations corresponding to the specified
/// subject and associated with the application identifier.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization corresponding to the subject/client.
/// whose result returns the authorizations corresponding to the subject/client.
/// </returns>
public virtual Task<TAuthorization> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken)
public virtual Task<ImmutableArray<TAuthorization>> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{

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

@ -72,16 +72,17 @@ namespace OpenIddict.Core
Task DeleteAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary>
/// Retrieves an authorization using its associated subject/client.
/// Retrieves the authorizations corresponding to the specified
/// subject and associated with the application identifier.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization corresponding to the subject/client.
/// whose result returns the authorizations corresponding to the subject/client.
/// </returns>
Task<TAuthorization> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken);
Task<ImmutableArray<TAuthorization>> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken);
/// <summary>
/// Retrieves an authorization using its unique identifier.

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

@ -100,9 +100,16 @@ namespace OpenIddict.Core
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
IQueryable<TApplication> Query(IQueryable<TApplication> applications)
{
var key = ConvertIdentifierFromString(identifier);
return from application in applications
where application.Id.Equals(key)
select application;
}
return GetAsync(applications => applications.Where(application => application.Id.Equals(key)), cancellationToken);
return GetAsync(Query, cancellationToken);
}
/// <summary>
@ -121,7 +128,14 @@ namespace OpenIddict.Core
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
return GetAsync(applications => applications.Where(application => application.ClientId.Equals(identifier)), cancellationToken);
IQueryable<TApplication> Query(IQueryable<TApplication> applications)
{
return from application in applications
where application.ClientId == identifier
select application;
}
return GetAsync(Query, cancellationToken);
}
/// <summary>

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

@ -85,16 +85,17 @@ namespace OpenIddict.Core
public abstract Task DeleteAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary>
/// Retrieves an authorization using its associated subject/client.
/// Retrieves the authorizations corresponding to the specified
/// subject and associated with the application identifier.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization corresponding to the subject/client.
/// whose result returns the authorizations corresponding to the subject/client.
/// </returns>
public virtual Task<TAuthorization> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken)
public virtual Task<ImmutableArray<TAuthorization>> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{
@ -106,13 +107,18 @@ namespace OpenIddict.Core
throw new ArgumentException("The client cannot be null or empty.", nameof(client));
}
var key = ConvertIdentifierFromString(client);
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations)
{
var key = ConvertIdentifierFromString(client);
return GetAsync(authorizations =>
from authorization in authorizations
where authorization.Application.Id.Equals(key)
where authorization.Subject == subject
select authorization, cancellationToken);
return from authorization in authorizations
where authorization.Application != null
where authorization.Application.Id.Equals(key)
where authorization.Subject == subject
select authorization;
}
return ListAsync(Query, cancellationToken);
}
/// <summary>
@ -131,9 +137,16 @@ namespace OpenIddict.Core
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations)
{
var key = ConvertIdentifierFromString(identifier);
return from authorization in authorizations
where authorization.Id.Equals(key)
select authorization;
}
return GetAsync(authorizations => authorizations.Where(authorization => authorization.Id.Equals(key)), cancellationToken);
return GetAsync(Query, cancellationToken);
}
/// <summary>

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

@ -98,9 +98,17 @@ namespace OpenIddict.Core
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
IQueryable<TToken> Query(IQueryable<TToken> tokens)
{
var key = ConvertIdentifierFromString(identifier);
return from token in tokens
where token.Application != null
where token.Application.Id.Equals(key)
select token;
}
return ListAsync(tokens => tokens.Where(token => token.Application.Id.Equals(key)), cancellationToken);
return ListAsync(Query, cancellationToken);
}
/// <summary>
@ -119,9 +127,17 @@ namespace OpenIddict.Core
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
IQueryable<TToken> Query(IQueryable<TToken> tokens)
{
var key = ConvertIdentifierFromString(identifier);
return from token in tokens
where token.Authorization != null
where token.Authorization.Id.Equals(key)
select token;
}
return ListAsync(tokens => tokens.Where(token => token.Authorization.Id.Equals(key)), cancellationToken);
return ListAsync(Query, cancellationToken);
}
/// <summary>
@ -140,7 +156,14 @@ namespace OpenIddict.Core
throw new ArgumentException("The hash cannot be null or empty.", nameof(hash));
}
return GetAsync(tokens => tokens.Where(token => token.Hash == hash), cancellationToken);
IQueryable<TToken> Query(IQueryable<TToken> tokens)
{
return from token in tokens
where token.Hash == hash
select token;
}
return GetAsync(Query, cancellationToken);
}
/// <summary>
@ -159,9 +182,16 @@ namespace OpenIddict.Core
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
IQueryable<TToken> Query(IQueryable<TToken> tokens)
{
var key = ConvertIdentifierFromString(identifier);
return from token in tokens
where token.Id.Equals(key)
select token;
}
return GetAsync(tokens => tokens.Where(token => token.Id.Equals(key)), cancellationToken);
return GetAsync(Query, cancellationToken);
}
/// <summary>
@ -180,7 +210,14 @@ namespace OpenIddict.Core
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject));
}
return ListAsync(tokens => tokens.Where(token => token.Subject == subject), cancellationToken);
IQueryable<TToken> Query(IQueryable<TToken> tokens)
{
return from token in tokens
where token.Subject == subject
select token;
}
return ListAsync(Query, cancellationToken);
}
/// <summary>

2
src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs

@ -369,7 +369,7 @@ namespace OpenIddict.EntityFramework
// Bind the authorization to the specified application, if applicable.
if (!string.IsNullOrEmpty(descriptor.ApplicationId))
{
var application = await Applications.FindAsync(new object[] { ConvertIdentifierFromString(descriptor.ApplicationId) }, cancellationToken);
var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(descriptor.ApplicationId));
if (application == null)
{
throw new InvalidOperationException("The application associated with the authorization cannot be found.");

4
src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs

@ -430,7 +430,7 @@ namespace OpenIddict.EntityFramework
// Bind the token to the specified client application, if applicable.
if (!string.IsNullOrEmpty(descriptor.ApplicationId))
{
var application = await Applications.FindAsync(new object[] { ConvertIdentifierFromString(descriptor.ApplicationId) }, cancellationToken);
var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(descriptor.ApplicationId));
if (application == null)
{
throw new InvalidOperationException("The application associated with the token cannot be found.");
@ -442,7 +442,7 @@ namespace OpenIddict.EntityFramework
// Bind the token to the specified authorization, if applicable.
if (!string.IsNullOrEmpty(descriptor.AuthorizationId))
{
var authorization = await Authorizations.FindAsync(new object[] { ConvertIdentifierFromString(descriptor.AuthorizationId) }, cancellationToken);
var authorization = await Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(descriptor.AuthorizationId));
if (authorization == null)
{
throw new InvalidOperationException("The authorization associated with the token cannot be found.");

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

@ -187,6 +187,48 @@ namespace OpenIddict.EntityFrameworkCore
await Context.SaveChangesAsync(cancellationToken);
}
/// <summary>
/// Retrieves the authorizations corresponding to the specified
/// subject and associated with the application identifier.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorizations corresponding to the subject/client.
/// </returns>
public override async Task<ImmutableArray<TAuthorization>> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject));
}
if (string.IsNullOrEmpty(client))
{
throw new ArgumentException("The client cannot be null or empty.", nameof(client));
}
// Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
// filtered using authorization.Application.Id.Equals(key). To work around this issue,
// this method is overriden to use an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, IQueryable<TApplication> applications)
{
var key = ConvertIdentifierFromString(client);
return from authorization in authorizations
where authorization.Subject == subject
join application in applications on authorization.Application.Id equals application.Id
where application.Id.Equals(key)
select authorization;
}
return ImmutableArray.Create(await Query(Authorizations, Applications).ToArrayAsync(cancellationToken));
}
/// <summary>
/// Executes the specified query.
/// </summary>

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

@ -172,6 +172,74 @@ namespace OpenIddict.EntityFrameworkCore
return Context.SaveChangesAsync(cancellationToken);
}
/// <summary>
/// Retrieves the list of tokens corresponding to the specified application identifier.
/// </summary>
/// <param name="identifier">The application identifier associated with the tokens.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified application.
/// </returns>
public override async Task<ImmutableArray<TToken>> FindByApplicationIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
// Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be
// filtered using token.Application.Id.Equals(key). To work around this issue,
// this method is overriden to use an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
IQueryable<TToken> Query(IQueryable<TApplication> applications, IQueryable<TToken> tokens)
{
var key = ConvertIdentifierFromString(identifier);
return from token in tokens
join application in applications on token.Application.Id equals application.Id
where application.Id.Equals(key)
select token;
}
return ImmutableArray.Create(await Query(Applications, Tokens).ToArrayAsync(cancellationToken));
}
/// <summary>
/// Retrieves the list of tokens corresponding to the specified authorization identifier.
/// </summary>
/// <param name="identifier">The authorization identifier associated with the tokens.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified authorization.
/// </returns>
public override async Task<ImmutableArray<TToken>> FindByAuthorizationIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
// Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be
// filtered using token.Authorization.Id.Equals(key). To work around this issue,
// this method is overriden to use an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
IQueryable<TToken> Query(IQueryable<TAuthorization> authorizations, IQueryable<TToken> tokens)
{
var key = ConvertIdentifierFromString(identifier);
return from token in tokens
join authorization in authorizations on token.Authorization.Id equals authorization.Id
where authorization.Id.Equals(key)
select token;
}
return ImmutableArray.Create(await Query(Authorizations, Tokens).ToArrayAsync(cancellationToken));
}
/// <summary>
/// Executes the specified query.
/// </summary>

Loading…
Cancel
Save