Browse Source

Update IOpenIddictTokenStore.FindByApplicationIdAsync()/FindByAuthorizationIdAsync() to work around an Entity Framework bug

pull/503/head
Kévin Chalet 8 years ago
parent
commit
a5376d46f0
  1. 20
      src/OpenIddict.Core/Stores/OpenIddictApplicationStore.cs
  2. 28
      src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
  3. 53
      src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
  4. 41
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
  5. 68
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs

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>

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

@ -106,13 +106,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 from authorization in authorizations
where authorization.Application != null
where authorization.Application.Id.Equals(key)
where authorization.Subject == subject
select authorization;
}
return GetAsync(authorizations =>
from authorization in authorizations
where authorization.Application.Id.Equals(key)
where authorization.Subject == subject
select authorization, cancellationToken);
return GetAsync(Query, cancellationToken);
}
/// <summary>
@ -131,9 +136,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>

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

@ -187,6 +187,47 @@ namespace OpenIddict.EntityFrameworkCore
await Context.SaveChangesAsync(cancellationToken);
}
/// <summary>
/// Retrieves an authorization using its associated subject/client.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization corresponding to the subject/client.
/// </returns>
public override Task<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 Query(Authorizations, Applications).SingleOrDefaultAsync(cancellationToken);
}
/// <summary>
/// Retrieves an authorization using its unique identifier.
/// </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>
/// Retrieves an token using its unique identifier.
/// </summary>

Loading…
Cancel
Save