From d7de292d93bc86f8b0646b26d7feff468a5eb4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Sat, 20 Oct 2018 14:28:31 +0200 Subject: [PATCH] Update OpenIddictMongoDbContext to dispose of the private semaphore --- .../OpenIddictMongoDbContext.cs | 12 ++++++++++- .../Stores/OpenIddictAuthorizationStore.cs | 2 ++ .../OpenIddictMongoDbContextTests.cs | 21 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs b/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs index af3aaadf..9e987266 100644 --- a/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs +++ b/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs @@ -19,7 +19,7 @@ namespace OpenIddict.MongoDb /// /// Exposes the MongoDB database used by the OpenIddict stores. /// - public class OpenIddictMongoDbContext : IOpenIddictMongoDbContext + public class OpenIddictMongoDbContext : IOpenIddictMongoDbContext, IDisposable { private readonly IOptionsMonitor _options; private readonly IServiceProvider _provider; @@ -35,6 +35,11 @@ namespace OpenIddict.MongoDb _semaphore = new SemaphoreSlim(1); } + /// + /// Disposes the semaphore held by this instance. + /// + public void Dispose() => _semaphore.Dispose(); + /// /// Gets the . /// @@ -49,6 +54,11 @@ namespace OpenIddict.MongoDb return new ValueTask(_database); } + if (cancellationToken.IsCancellationRequested) + { + return new ValueTask(Task.FromCanceled(cancellationToken)); + } + async Task ExecuteAsync() { var options = _options.CurrentValue; diff --git a/src/OpenIddict.MongoDb/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.MongoDb/Stores/OpenIddictAuthorizationStore.cs index 9f7053c9..e805119e 100644 --- a/src/OpenIddict.MongoDb/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.MongoDb/Stores/OpenIddictAuthorizationStore.cs @@ -299,6 +299,8 @@ namespace OpenIddict.MongoDb var database = await Context.GetDatabaseAsync(cancellationToken); var collection = database.GetCollection(Options.CurrentValue.AuthorizationsCollectionName); + // Note: Enumerable.All() is deliberately used without the extension method syntax to ensure + // ImmutableArrayExtensions.All() (which is not supported by MongoDB) is not used instead. return ImmutableArray.CreateRange(await collection.Find(authorization => authorization.Subject == subject && authorization.ApplicationId == ObjectId.Parse(client) && diff --git a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs index 319cbc3e..830c67c0 100644 --- a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs +++ b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs @@ -20,6 +20,27 @@ namespace OpenIddict.MongoDb.Tests { public class OpenIddictMongoDbContextTests { + [Fact] + public async Task GetDatabaseAsync_ThrowsAnExceptionForCanceledToken() + { + // Arrange + var services = new ServiceCollection(); + var provider = services.BuildServiceProvider(); + + var options = Mock.Of>(); + var token = new CancellationToken(canceled: true); + + var context = new OpenIddictMongoDbContext(options, provider); + + // Act and assert + var exception = await Assert.ThrowsAsync(async delegate + { + await context.GetDatabaseAsync(token); + }); + + Assert.Equal(token, exception.CancellationToken); + } + [Fact] public async Task GetDatabaseAsync_ThrowsAnExceptionForNullOptions() {