diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs index 5a64369f..210dc783 100644 --- a/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs @@ -141,6 +141,17 @@ namespace OpenIddict.Abstractions /// Task> FindAsync([NotNull] string subject, [NotNull] string client, [NotNull] string status, [NotNull] string type, ImmutableArray scopes, CancellationToken cancellationToken = default); + /// + /// Retrieves the list of authorizations corresponding to the specified application identifier. + /// + /// The application identifier associated with the authorizations. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the specified application. + /// + Task> FindByApplicationIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + /// /// Retrieves an authorization using its unique identifier. /// diff --git a/src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs b/src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs index 77324e8a..211936a3 100644 --- a/src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs @@ -125,6 +125,17 @@ namespace OpenIddict.Abstractions [NotNull] string status, [NotNull] string type, ImmutableArray scopes, CancellationToken cancellationToken); + /// + /// Retrieves the list of authorizations corresponding to the specified application identifier. + /// + /// The application identifier associated with the authorizations. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the specified application. + /// + Task> FindByApplicationIdAsync([NotNull] string identifier, CancellationToken cancellationToken); + /// /// Retrieves an authorization using its unique identifier. /// diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs index 1daa77d4..26d5bb83 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs @@ -446,6 +446,26 @@ namespace OpenIddict.Core builder.ToImmutable(); } + /// + /// Retrieves the list of authorizations corresponding to the specified application identifier. + /// + /// The application identifier associated with the authorizations. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the specified application. + /// + public virtual Task> FindByApplicationIdAsync( + [NotNull] string identifier, CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(identifier)) + { + throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + } + + return Store.FindByApplicationIdAsync(identifier, cancellationToken); + } + /// /// Retrieves an authorization using its unique identifier. /// @@ -1082,6 +1102,9 @@ namespace OpenIddict.Core async Task> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, string status, string type, ImmutableArray scopes, CancellationToken cancellationToken) => (await FindAsync(subject, client, status, type, scopes, cancellationToken)).CastArray(); + async Task> IOpenIddictAuthorizationManager.FindByApplicationIdAsync(string identifier, CancellationToken cancellationToken) + => (await FindByApplicationIdAsync(identifier, cancellationToken)).CastArray(); + async Task IOpenIddictAuthorizationManager.FindByIdAsync(string identifier, CancellationToken cancellationToken) => await FindByIdAsync(identifier, cancellationToken); diff --git a/src/OpenIddict.EntityFramework.Models/OpenIddictApplication.cs b/src/OpenIddict.EntityFramework.Models/OpenIddictApplication.cs index e60df750..b9962550 100644 --- a/src/OpenIddict.EntityFramework.Models/OpenIddictApplication.cs +++ b/src/OpenIddict.EntityFramework.Models/OpenIddictApplication.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; namespace OpenIddict.EntityFramework.Models { @@ -24,6 +25,7 @@ namespace OpenIddict.EntityFramework.Models /// /// Represents an OpenIddict application. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; ClientId = {ClientId,nq} ; Type = {Type,nq}")] public class OpenIddictApplication where TKey : IEquatable { /// diff --git a/src/OpenIddict.EntityFramework.Models/OpenIddictAuthorization.cs b/src/OpenIddict.EntityFramework.Models/OpenIddictAuthorization.cs index 7ebfd69d..d7996a7e 100644 --- a/src/OpenIddict.EntityFramework.Models/OpenIddictAuthorization.cs +++ b/src/OpenIddict.EntityFramework.Models/OpenIddictAuthorization.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; namespace OpenIddict.EntityFramework.Models { @@ -24,6 +25,7 @@ namespace OpenIddict.EntityFramework.Models /// /// Represents an OpenIddict authorization. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; Type = {Type,nq} ; Status = {Status,nq}")] public class OpenIddictAuthorization where TKey : IEquatable { /// diff --git a/src/OpenIddict.EntityFramework.Models/OpenIddictScope.cs b/src/OpenIddict.EntityFramework.Models/OpenIddictScope.cs index 30967531..91d487f3 100644 --- a/src/OpenIddict.EntityFramework.Models/OpenIddictScope.cs +++ b/src/OpenIddict.EntityFramework.Models/OpenIddictScope.cs @@ -5,6 +5,7 @@ */ using System; +using System.Diagnostics; namespace OpenIddict.EntityFramework.Models { @@ -23,6 +24,7 @@ namespace OpenIddict.EntityFramework.Models /// /// Represents an OpenIddict scope. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Name = {Name,nq}")] public class OpenIddictScope where TKey : IEquatable { /// diff --git a/src/OpenIddict.EntityFramework.Models/OpenIddictToken.cs b/src/OpenIddict.EntityFramework.Models/OpenIddictToken.cs index 378f8f5c..411b9f74 100644 --- a/src/OpenIddict.EntityFramework.Models/OpenIddictToken.cs +++ b/src/OpenIddict.EntityFramework.Models/OpenIddictToken.cs @@ -5,6 +5,7 @@ */ using System; +using System.Diagnostics; namespace OpenIddict.EntityFramework.Models { @@ -23,6 +24,7 @@ namespace OpenIddict.EntityFramework.Models /// /// Represents an OpenIddict token. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; Type = {Type,nq} ; Status = {Status,nq}")] public class OpenIddictToken where TKey : IEquatable { /// diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs index 6acf5468..da315e4d 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs @@ -378,6 +378,31 @@ namespace OpenIddict.EntityFramework builder.ToImmutable(); } + /// + /// Retrieves the list of authorizations corresponding to the specified application identifier. + /// + /// The application identifier associated with the authorizations. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the specified application. + /// + public virtual async Task> FindByApplicationIdAsync( + [NotNull] string identifier, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(identifier)) + { + throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + } + + var key = ConvertIdentifierFromString(identifier); + + return ImmutableArray.CreateRange( + await (from authorization in Authorizations.Include(authorization => authorization.Application) + where authorization.Application.Id.Equals(key) + select authorization).ToListAsync(cancellationToken)); + } + /// /// Retrieves an authorization using its unique identifier. /// diff --git a/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictApplication.cs b/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictApplication.cs index e5306535..c452d1a9 100644 --- a/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictApplication.cs +++ b/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictApplication.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; namespace OpenIddict.EntityFrameworkCore.Models { @@ -31,6 +32,7 @@ namespace OpenIddict.EntityFrameworkCore.Models /// /// Represents an OpenIddict application. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; ClientId = {ClientId,nq} ; Type = {Type,nq}")] public class OpenIddictApplication where TKey : IEquatable { /// diff --git a/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictAuthorization.cs b/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictAuthorization.cs index 67cc0272..6f4f210e 100644 --- a/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictAuthorization.cs +++ b/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictAuthorization.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; namespace OpenIddict.EntityFrameworkCore.Models { @@ -31,6 +32,7 @@ namespace OpenIddict.EntityFrameworkCore.Models /// /// Represents an OpenIddict authorization. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; Type = {Type,nq} ; Status = {Status,nq}")] public class OpenIddictAuthorization where TKey : IEquatable { /// diff --git a/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictScope.cs b/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictScope.cs index b28ba8a0..0c739c04 100644 --- a/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictScope.cs +++ b/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictScope.cs @@ -5,6 +5,7 @@ */ using System; +using System.Diagnostics; namespace OpenIddict.EntityFrameworkCore.Models { @@ -23,6 +24,7 @@ namespace OpenIddict.EntityFrameworkCore.Models /// /// Represents an OpenIddict scope. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Name = {Name,nq}")] public class OpenIddictScope where TKey : IEquatable { /// diff --git a/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictToken.cs b/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictToken.cs index 92cca5d3..5dc84464 100644 --- a/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictToken.cs +++ b/src/OpenIddict.EntityFrameworkCore.Models/OpenIddictToken.cs @@ -5,6 +5,7 @@ */ using System; +using System.Diagnostics; namespace OpenIddict.EntityFrameworkCore.Models { @@ -31,6 +32,7 @@ namespace OpenIddict.EntityFrameworkCore.Models /// /// Represents an OpenIddict token. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; Type = {Type,nq} ; Status = {Status,nq}")] public class OpenIddictToken where TKey : IEquatable { /// diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs index 6607c226..77a3d95a 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs @@ -277,16 +277,14 @@ namespace OpenIddict.EntityFrameworkCore // 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 Query(IQueryable authorizations, - IQueryable applications, TKey key, string principal) - => from authorization in authorizations.Include(authorization => authorization.Application).AsTracking() - where authorization.Subject == principal - join application in applications.AsTracking() on authorization.Application.Id equals application.Id - where application.Id.Equals(key) - select authorization; - - return ImmutableArray.CreateRange(await Query( - Authorizations, Applications, ConvertIdentifierFromString(client), subject).ToListAsync(cancellationToken)); + var key = ConvertIdentifierFromString(client); + + return ImmutableArray.CreateRange( + await (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking() + where authorization.Subject == subject + join application in Applications.AsTracking() on authorization.Application.Id equals application.Id + where application.Id.Equals(key) + select authorization).ToListAsync(cancellationToken)); } /// @@ -324,16 +322,14 @@ namespace OpenIddict.EntityFrameworkCore // 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 Query(IQueryable authorizations, - IQueryable applications, TKey key, string principal, string state) - => from authorization in authorizations.Include(authorization => authorization.Application).AsTracking() - where authorization.Subject == principal && authorization.Status == state - join application in applications.AsTracking() on authorization.Application.Id equals application.Id - where application.Id.Equals(key) - select authorization; + var key = ConvertIdentifierFromString(client); - return ImmutableArray.CreateRange(await Query( - Authorizations, Applications, ConvertIdentifierFromString(client), subject, status).ToListAsync(cancellationToken)); + return ImmutableArray.CreateRange( + await (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking() + where authorization.Subject == subject && authorization.Status == status + join application in Applications.AsTracking() on authorization.Application.Id equals application.Id + where application.Id.Equals(key) + select authorization).ToListAsync(cancellationToken)); } /// @@ -377,18 +373,16 @@ namespace OpenIddict.EntityFrameworkCore // 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 Query(IQueryable authorizations, - IQueryable applications, TKey key, string principal, string state, string kind) - => from authorization in authorizations.Include(authorization => authorization.Application).AsTracking() - where authorization.Subject == principal && - authorization.Status == state && - authorization.Type == kind - join application in applications.AsTracking() on authorization.Application.Id equals application.Id - where application.Id.Equals(key) - select authorization; - - return ImmutableArray.CreateRange(await Query( - Authorizations, Applications, ConvertIdentifierFromString(client), subject, status, type).ToListAsync(cancellationToken)); + var key = ConvertIdentifierFromString(client); + + return ImmutableArray.CreateRange( + await (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking() + where authorization.Subject == subject && + authorization.Status == status && + authorization.Type == type + join application in Applications.AsTracking() on authorization.Application.Id equals application.Id + where application.Id.Equals(key) + select authorization).ToListAsync(cancellationToken)); } /// @@ -435,6 +429,37 @@ namespace OpenIddict.EntityFrameworkCore builder.ToImmutable(); } + /// + /// Retrieves the list of authorizations corresponding to the specified application identifier. + /// + /// The application identifier associated with the authorizations. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the specified application. + /// + public virtual async Task> 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 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. + + var key = ConvertIdentifierFromString(identifier); + + return ImmutableArray.CreateRange( + await (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking() + join application in Applications.AsTracking() on authorization.Application.Id equals application.Id + where application.Id.Equals(identifier) + select authorization).ToListAsync(cancellationToken)); + } + /// /// Retrieves an authorization using its unique identifier. /// @@ -504,14 +529,12 @@ namespace OpenIddict.EntityFrameworkCore async Task RetrieveApplicationIdAsync() { - IQueryable Query(IQueryable authorizations, TKey key) - => from element in authorizations.AsTracking() - where element.Id.Equals(key) && - element.Application != null - select element.Application.Id; - - return ConvertIdentifierToString(await GetAsync( - (authorizations, key) => Query(authorizations, key), authorization.Id, cancellationToken)); + var key = await (from element in Authorizations.AsTracking() + where element.Id.Equals(authorization.Id) && + element.Application != null + select element.Application.Id).FirstOrDefaultAsync(cancellationToken); + + return ConvertIdentifierToString(key); } return new ValueTask(RetrieveApplicationIdAsync()); diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs index a261b375..1432b1c8 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs @@ -225,15 +225,19 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The client cannot be null or empty.", nameof(client)); } - IQueryable Query(IQueryable applications, IQueryable tokens, TKey key, string principal) - => from token in tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() - where token.Subject == subject - join application in applications.AsTracking() on token.Application.Id equals application.Id - where application.Id.Equals(key) - select token; - - return ImmutableArray.CreateRange(await Query(Applications, Tokens, - ConvertIdentifierFromString(client), subject).ToListAsync(cancellationToken)); + // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be + // filtered using token.Application.Id.Equals(key). To work around this issue, + // this compiled query uses an explicit join before applying the equality check. + // See https://github.com/openiddict/openiddict-core/issues/499 for more information. + + var key = ConvertIdentifierFromString(client); + + return ImmutableArray.CreateRange( + await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() + where token.Subject == subject + join application in Applications.AsTracking() on token.Application.Id equals application.Id + where application.Id.Equals(key) + select token).ToListAsync(cancellationToken)); } /// @@ -266,17 +270,20 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The status cannot be null or empty.", nameof(status)); } - IQueryable Query(IQueryable applications, - IQueryable tokens, TKey key, string principal, string state) - => from token in tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() - where token.Subject == subject && - token.Status == status - join application in applications.AsTracking() on token.Application.Id equals application.Id - where application.Id.Equals(key) - select token; + // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be + // filtered using token.Application.Id.Equals(key). To work around this issue, + // this compiled query uses an explicit join before applying the equality check. + // See https://github.com/openiddict/openiddict-core/issues/499 for more information. + + var key = ConvertIdentifierFromString(client); - return ImmutableArray.CreateRange(await Query(Applications, Tokens, - ConvertIdentifierFromString(client), subject, status).ToListAsync(cancellationToken)); + return ImmutableArray.CreateRange( + await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() + where token.Subject == subject && + token.Status == status + join application in Applications.AsTracking() on token.Application.Id equals application.Id + where application.Id.Equals(key) + select token).ToListAsync(cancellationToken)); } /// @@ -320,18 +327,16 @@ namespace OpenIddict.EntityFrameworkCore // this compiled query uses an explicit join before applying the equality check. // See https://github.com/openiddict/openiddict-core/issues/499 for more information. - IQueryable Query(IQueryable applications, - IQueryable tokens, TKey key, string principal, string state, string kind) - => from token in tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() - where token.Subject == subject && - token.Status == status && - token.Type == type - join application in applications.AsTracking() on token.Application.Id equals application.Id - where application.Id.Equals(key) - select token; - - return ImmutableArray.CreateRange(await Query(Applications, Tokens, - ConvertIdentifierFromString(client), subject, status, type).ToListAsync(cancellationToken)); + var key = ConvertIdentifierFromString(client); + + return ImmutableArray.CreateRange( + await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() + where token.Subject == subject && + token.Status == status && + token.Type == type + join application in Applications.AsTracking() on token.Application.Id equals application.Id + where application.Id.Equals(key) + select token).ToListAsync(cancellationToken)); } /// @@ -355,14 +360,13 @@ namespace OpenIddict.EntityFrameworkCore // 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 Query(IQueryable applications, IQueryable tokens, TKey key) - => from token in tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() - join application in applications.AsTracking() on token.Application.Id equals application.Id - where application.Id.Equals(key) - select token; + var key = ConvertIdentifierFromString(identifier); - return ImmutableArray.CreateRange(await Query( - Applications, Tokens, ConvertIdentifierFromString(identifier)).ToListAsync(cancellationToken)); + return ImmutableArray.CreateRange( + await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() + join application in Applications.AsTracking() on token.Application.Id equals application.Id + where application.Id.Equals(key) + select token).ToListAsync(cancellationToken)); } /// @@ -386,14 +390,13 @@ namespace OpenIddict.EntityFrameworkCore // 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 Query(IQueryable authorizations, IQueryable tokens, TKey key) - => from token in tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() - join authorization in authorizations.AsTracking() on token.Authorization.Id equals authorization.Id - where authorization.Id.Equals(key) - select token; + var key = ConvertIdentifierFromString(identifier); - return ImmutableArray.CreateRange(await Query( - Authorizations, Tokens, ConvertIdentifierFromString(identifier)).ToListAsync(cancellationToken)); + return ImmutableArray.CreateRange( + await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() + join authorization in Authorizations.AsTracking() on token.Authorization.Id equals authorization.Id + where authorization.Id.Equals(key) + select token).ToListAsync(cancellationToken)); } /// @@ -486,13 +489,12 @@ namespace OpenIddict.EntityFrameworkCore async Task RetrieveApplicationIdAsync() { - IQueryable Query(IQueryable tokens, TKey key) - => from element in tokens.AsTracking() - where element.Id.Equals(key) && - element.Application != null - select element.Application.Id; + var key = await (from element in Tokens.AsTracking() + where element.Id.Equals(token.Id) && + element.Application != null + select element.Application.Id).FirstOrDefaultAsync(cancellationToken); - return ConvertIdentifierToString(await GetAsync((tokens, key) => Query(tokens, key), token.Id, cancellationToken)); + return ConvertIdentifierToString(key); } return new ValueTask(RetrieveApplicationIdAsync()); @@ -548,13 +550,12 @@ namespace OpenIddict.EntityFrameworkCore async Task RetrieveAuthorizationIdAsync() { - IQueryable Query(IQueryable tokens, TKey key) - => from element in tokens.AsTracking() - where element.Id.Equals(key) && - element.Authorization != null - select element.Authorization.Id; + var key = await (from element in Tokens.AsTracking() + where element.Id.Equals(token.Id) && + element.Authorization != null + select element.Authorization.Id).FirstOrDefaultAsync(cancellationToken); - return ConvertIdentifierToString(await GetAsync((tokens, key) => Query(tokens, key), token.Id, cancellationToken)); + return ConvertIdentifierToString(key); } return new ValueTask(RetrieveAuthorizationIdAsync()); diff --git a/src/OpenIddict.MongoDb.Models/OpenIddictApplication.cs b/src/OpenIddict.MongoDb.Models/OpenIddictApplication.cs index 27bbce77..d2a4a958 100644 --- a/src/OpenIddict.MongoDb.Models/OpenIddictApplication.cs +++ b/src/OpenIddict.MongoDb.Models/OpenIddictApplication.cs @@ -5,6 +5,7 @@ */ using System; +using System.Diagnostics; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; @@ -13,6 +14,7 @@ namespace OpenIddict.MongoDb.Models /// /// Represents an OpenIddict application. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; ClientId = {ClientId,nq} ; Type = {Type,nq}")] public class OpenIddictApplication { /// diff --git a/src/OpenIddict.MongoDb.Models/OpenIddictAuthorization.cs b/src/OpenIddict.MongoDb.Models/OpenIddictAuthorization.cs index a4c5c760..7b68d677 100644 --- a/src/OpenIddict.MongoDb.Models/OpenIddictAuthorization.cs +++ b/src/OpenIddict.MongoDb.Models/OpenIddictAuthorization.cs @@ -5,6 +5,7 @@ */ using System; +using System.Diagnostics; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; @@ -13,6 +14,7 @@ namespace OpenIddict.MongoDb.Models /// /// Represents an OpenIddict authorization. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; Type = {Type,nq} ; Status = {Status,nq}")] public class OpenIddictAuthorization { /// diff --git a/src/OpenIddict.MongoDb.Models/OpenIddictScope.cs b/src/OpenIddict.MongoDb.Models/OpenIddictScope.cs index 586c98da..46c2dfd4 100644 --- a/src/OpenIddict.MongoDb.Models/OpenIddictScope.cs +++ b/src/OpenIddict.MongoDb.Models/OpenIddictScope.cs @@ -5,6 +5,7 @@ */ using System; +using System.Diagnostics; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; @@ -13,6 +14,7 @@ namespace OpenIddict.MongoDb.Models /// /// Represents an OpenIddict scope. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Name = {Name,nq}")] public class OpenIddictScope { /// diff --git a/src/OpenIddict.MongoDb.Models/OpenIddictToken.cs b/src/OpenIddict.MongoDb.Models/OpenIddictToken.cs index c212b5d5..65ed4398 100644 --- a/src/OpenIddict.MongoDb.Models/OpenIddictToken.cs +++ b/src/OpenIddict.MongoDb.Models/OpenIddictToken.cs @@ -5,6 +5,7 @@ */ using System; +using System.Diagnostics; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; @@ -13,6 +14,7 @@ namespace OpenIddict.MongoDb.Models /// /// Represents an OpenIddict token. /// + [DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; Type = {Type,nq} ; Status = {Status,nq}")] public class OpenIddictToken { /// diff --git a/src/OpenIddict.MongoDb/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.MongoDb/Stores/OpenIddictAuthorizationStore.cs index 0da73d37..7ecbeec1 100644 --- a/src/OpenIddict.MongoDb/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.MongoDb/Stores/OpenIddictAuthorizationStore.cs @@ -314,6 +314,30 @@ namespace OpenIddict.MongoDb Enumerable.All(scopes, scope => authorization.Scopes.Contains(scope))).ToListAsync(cancellationToken)); } + /// + /// Retrieves the list of authorizations corresponding to the specified application identifier. + /// + /// The application identifier associated with the authorizations. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the specified application. + /// + public virtual async Task> FindByApplicationIdAsync( + [NotNull] string identifier, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(identifier)) + { + throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + } + + var database = await Context.GetDatabaseAsync(cancellationToken); + var collection = database.GetCollection(Options.Value.AuthorizationsCollectionName); + + return ImmutableArray.CreateRange(await collection.Find(authorization => + authorization.ApplicationId == ObjectId.Parse(identifier)).ToListAsync(cancellationToken)); + } + /// /// Retrieves an authorization using its unique identifier. ///