Browse Source

Bump the dependencies to their latest version and update the OpenIddict/Quartz integration to work with both 3.x and 4.x

pull/2547/head
Kévin Chalet 2 weeks ago
parent
commit
359b1fc5ea
  1. 4
      Directory.Build.props
  2. 156
      Directory.Packages.props
  3. 30
      WorkloadRollback.json
  4. 8
      global.json
  5. 1
      sandbox/OpenIddict.Sandbox.AspNet.Client/OpenIddict.Sandbox.AspNet.Client.csproj
  6. 2
      sandbox/OpenIddict.Sandbox.AspNetCore.Client/OpenIddict.Sandbox.AspNetCore.Client.csproj
  7. 2
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/OpenIddict.Sandbox.AspNetCore.Server.csproj
  8. 7
      src/OpenIddict.Quartz/OpenIddict.Quartz.csproj
  9. 27
      src/OpenIddict.Quartz/OpenIddictQuartzConfiguration.cs
  10. 36
      src/OpenIddict.Quartz/OpenIddictQuartzExtensions.cs
  11. 39
      src/OpenIddict.Quartz/OpenIddictQuartzJob.cs
  12. 44
      test/OpenIddict.Quartz.Tests/OpenIddictQuartzConfigurationTests.cs
  13. 17
      test/OpenIddict.Quartz.Tests/OpenIddictQuartzExtensionsTests.cs
  14. 161
      test/OpenIddict.Quartz.Tests/OpenIddictQuartzJobTests.cs

4
Directory.Build.props

@ -128,25 +128,21 @@
<NetCoreAndroidTargetFrameworks
Condition=" '$(NetCoreAndroidTargetFrameworks)' == '' And '$(SupportsAndroidTargeting)' == 'true' ">
net9.0-android;
net10.0-android
</NetCoreAndroidTargetFrameworks>
<NetCoreIOSTargetFrameworks
Condition=" '$(NetCoreIOSTargetFrameworks)' == '' And '$(SupportsIOSTargeting)' == 'true' ">
net9.0-ios;
net10.0-ios
</NetCoreIOSTargetFrameworks>
<NetCoreMacCatalystTargetFrameworks
Condition=" '$(NetCoreMacCatalystTargetFrameworks)' == '' And '$(SupportsMacCatalystTargeting)' == 'true' ">
net9.0-maccatalyst;
net10.0-maccatalyst
</NetCoreMacCatalystTargetFrameworks>
<NetCoreMacOSTargetFrameworks
Condition=" '$(NetCoreMacOSTargetFrameworks)' == '' And '$(SupportsMacOSTargeting)' == 'true' ">
net9.0-macos;
net10.0-macos
</NetCoreMacOSTargetFrameworks>

156
Directory.Packages.props

@ -22,25 +22,26 @@
Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' And $([MSBuild]::VersionEquals($(TargetFrameworkVersion), '4.6.2')) ">
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.6.2" />
<PackageVersion Include="EntityFramework" Version="6.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.3.12" />
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="6.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="2.3.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.30" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.30" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.Owin.Security" Version="4.2.3" />
<PackageVersion Include="Microsoft.Windows.SDK.Contracts" Version="10.0.17763.1000" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.18.2" />
<PackageVersion Include="Quartz" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.Net.Http.Json" Version="8.0.1" />
@ -60,19 +61,19 @@
<ItemGroup Label="Package versions for .NET Framework 4.7.2"
Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' And $([MSBuild]::VersionEquals($(TargetFrameworkVersion), '4.7.2')) ">
<PackageVersion Include="EntityFramework" Version="6.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.3.12" />
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="6.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="2.3.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.30" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.30" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.2" />
@ -80,7 +81,8 @@
<PackageVersion Include="Microsoft.Windows.SDK.Contracts" Version="10.0.17763.1000" />
<PackageVersion Include="MongoDB.Bson" Version="3.10.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.18.2" />
<PackageVersion Include="Quartz" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.Interactive.Async" Version="7.0.1" />
@ -92,8 +94,8 @@
-->
<PackageVersion Include="AngleSharp" Version="1.5.2" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.7.1" />
<PackageVersion Include="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="2.3.12" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="Microsoft.Owin.Testing" Version="4.2.3" />
<PackageVersion Include="Moq" Version="4.18.4" />
@ -111,19 +113,19 @@
<ItemGroup Label="Package versions for .NET Framework 4.8"
Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' And $([MSBuild]::VersionEquals($(TargetFrameworkVersion), '4.8.0')) ">
<PackageVersion Include="EntityFramework" Version="6.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.3.12" />
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="6.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="2.3.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.30" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.30" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.2" />
@ -131,7 +133,8 @@
<PackageVersion Include="Microsoft.Windows.SDK.Contracts" Version="10.0.17763.1000" />
<PackageVersion Include="MongoDB.Bson" Version="3.10.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.18.2" />
<PackageVersion Include="Quartz" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.Interactive.Async" Version="7.0.1" />
@ -143,8 +146,8 @@
-->
<PackageVersion Include="AngleSharp" Version="1.5.2" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.7.1" />
<PackageVersion Include="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="2.3.12" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="Microsoft.Owin.Testing" Version="4.2.3" />
<PackageVersion Include="Moq" Version="4.18.4" />
@ -166,12 +169,12 @@
<PackageVersion Include="Microsoft.AspNet.Mvc" Version="5.3.0" />
<PackageVersion Include="Microsoft.AspNet.Web.Optimization" Version="1.1.3" />
<PackageVersion Include="Microsoft.AspNet.WebApi.Owin" Version="5.3.0" />
<PackageVersion Include="Microsoft.AspNetCore" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Identity" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.Identity" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc" Version="2.3.12" />
<PackageVersion Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.12" />
<PackageVersion Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="4.1.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.3.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
@ -197,23 +200,24 @@
<ItemGroup Label="Package versions for .NET 8.0"
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionEquals($(TargetFrameworkVersion), '8.0')) ">
<PackageVersion Include="EntityFramework" Version="6.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="8.0.29" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.29" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="8.0.30" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.30" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.30" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="8.10.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.30" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.2" />
<PackageVersion Include="MongoDB.Bson" Version="3.10.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.18.2" />
<PackageVersion Include="Quartz" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="8.0.4" />
<PackageVersion Include="Xamarin.AndroidX.Browser" Version="1.10.0.1" />
@ -222,7 +226,7 @@
-->
<PackageVersion Include="AngleSharp" Version="1.5.2" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.7.1" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="8.0.29" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="8.0.30" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="System.Linq.Async" Version="7.0.1" />
@ -239,23 +243,24 @@
<ItemGroup Label="Package versions for .NET 9.0"
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionEquals($(TargetFrameworkVersion), '9.0')) ">
<PackageVersion Include="EntityFramework" Version="6.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="9.0.18" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.18" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.18" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.18" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.18" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="9.0.18" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="9.0.19" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.19" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.19" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.19" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.19" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="9.0.19" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.10.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.18" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.18" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="9.0.18" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.19" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.19" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="9.0.19" />
<PackageVersion Include="MongoDB.Bson" Version="3.10.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.18.2" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="9.0.18" />
<PackageVersion Include="Quartz" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="9.0.19" />
<PackageVersion Include="Xamarin.AndroidX.Browser" Version="1.10.0.1" />
<!--
@ -263,8 +268,8 @@
-->
<PackageVersion Include="AngleSharp" Version="1.5.2" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.7.1" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.18" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.18" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="9.0.19" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.19" />
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="System.Linq.Async" Version="7.0.1" />
</ItemGroup>
@ -280,23 +285,23 @@
<ItemGroup Label="Package versions for .NET 10.0"
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionEquals($(TargetFrameworkVersion), '10.0')) ">
<PackageVersion Include="EntityFramework" Version="6.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="10.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="10.0.10" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="10.0.11" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.8.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="10.0.11" />
<PackageVersion Include="MongoDB.Bson" Version="3.10.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.18.2" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="10.0.10" />
<PackageVersion Include="Quartz" Version="4.0.0" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="10.0.11" />
<PackageVersion Include="Xamarin.AndroidX.Browser" Version="1.10.0.1" />
<!--
@ -304,8 +309,8 @@
-->
<PackageVersion Include="AngleSharp" Version="1.5.2" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.7.1" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.10" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.11" />
<PackageVersion Include="Moq" Version="4.18.4" />
<!--
@ -314,12 +319,11 @@
<PackageVersion Include="Dapplo.Microsoft.Extensions.Hosting.AppServices" Version="1.0.14" />
<PackageVersion Include="Dapplo.Microsoft.Extensions.Hosting.WinForms" Version="1.0.14" />
<PackageVersion Include="Dapplo.Microsoft.Extensions.Hosting.Wpf" Version="1.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.10" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="10.0.80" />
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="10.0.80" />
<PackageVersion Include="Quartz.Extensions.Hosting" Version="3.18.2" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.11" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.11" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.11" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="10.0.100" />
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="10.0.100" />
<PackageVersion Include="Spectre.Console" Version="0.57.2" />
</ItemGroup>
@ -335,24 +339,25 @@
Condition=" '$(TargetFrameworkIdentifier)' == '.NETStandard' And $([MSBuild]::VersionEquals($(TargetFrameworkVersion), '2.0')) ">
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.6.2" />
<PackageVersion Include="EntityFramework" Version="6.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.12" />
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="6.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="2.3.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.30" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.30" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.2" />
<PackageVersion Include="MongoDB.Bson" Version="3.10.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
<PackageVersion Include="NamedPipeServerStream.NetFrameworkVersion" Version="1.1.13" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.18.2" />
<PackageVersion Include="Quartz" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
@ -365,7 +370,7 @@
-->
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.6.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.6.0" />
<PackageVersion Include="Scriban" Version="7.2.5" />
<PackageVersion Include="Scriban" Version="7.2.7" />
<PackageVersion Include="System.Interactive" Version="7.0.1" />
</ItemGroup>
@ -380,23 +385,24 @@
<ItemGroup Label="Package versions for .NET Standard 2.1"
Condition=" '$(TargetFrameworkIdentifier)' == '.NETStandard' And $([MSBuild]::VersionEquals($(TargetFrameworkVersion), '2.1')) ">
<PackageVersion Include="EntityFramework" Version="6.5.2" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.11" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="2.3.12" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="2.3.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.30" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.29" />
<PackageVersion Include="Microsoft.Extensions.WebEncoders" Version="8.0.30" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols" Version="8.19.2" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.2" />
<PackageVersion Include="MongoDB.Bson" Version="3.10.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
<PackageVersion Include="NamedPipeServerStream.NetFrameworkVersion" Version="1.1.13" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="3.18.2" />
<PackageVersion Include="Quartz" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="Quartz.Extensions.DependencyInjection" Version="[3.20.1, 4.0.0)" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />

30
WorkloadRollback.json

@ -1,18 +1,18 @@
{
"microsoft.net.sdk.android": "36.1.43/10.0.100",
"microsoft.net.sdk.ios": "26.5.10284/10.0.100",
"microsoft.net.sdk.maccatalyst": "26.5.10284/10.0.100",
"microsoft.net.sdk.macos": "26.5.10284/10.0.100",
"microsoft.net.sdk.android": "36.1.69/10.0.100",
"microsoft.net.sdk.ios": "26.5.10301/10.0.100",
"microsoft.net.sdk.maccatalyst": "26.5.10301/10.0.100",
"microsoft.net.sdk.macos": "26.5.10301/10.0.100",
"microsoft.net.sdk.maui": "10.0.20/10.0.100",
"microsoft.net.sdk.tvos": "26.5.10284/10.0.100",
"microsoft.net.workload.mono.toolchain.current": "10.0.110/10.0.100",
"microsoft.net.workload.emscripten.current": "10.0.110/10.0.100",
"microsoft.net.workload.emscripten.net6": "10.0.110/10.0.100",
"microsoft.net.workload.emscripten.net7": "10.0.110/10.0.100",
"microsoft.net.workload.emscripten.net8": "10.0.110/10.0.100",
"microsoft.net.workload.emscripten.net9": "10.0.110/10.0.100",
"microsoft.net.workload.mono.toolchain.net6": "10.0.110/10.0.100",
"microsoft.net.workload.mono.toolchain.net7": "10.0.110/10.0.100",
"microsoft.net.workload.mono.toolchain.net8": "10.0.110/10.0.100",
"microsoft.net.workload.mono.toolchain.net9": "10.0.110/10.0.100"
"microsoft.net.sdk.tvos": "26.5.10301/10.0.100",
"microsoft.net.workload.mono.toolchain.current": "10.0.111/10.0.100",
"microsoft.net.workload.emscripten.current": "10.0.111/10.0.100",
"microsoft.net.workload.emscripten.net6": "10.0.111/10.0.100",
"microsoft.net.workload.emscripten.net7": "10.0.111/10.0.100",
"microsoft.net.workload.emscripten.net8": "10.0.111/10.0.100",
"microsoft.net.workload.emscripten.net9": "10.0.111/10.0.100",
"microsoft.net.workload.mono.toolchain.net6": "10.0.111/10.0.100",
"microsoft.net.workload.mono.toolchain.net7": "10.0.111/10.0.100",
"microsoft.net.workload.mono.toolchain.net8": "10.0.111/10.0.100",
"microsoft.net.workload.mono.toolchain.net9": "10.0.111/10.0.100"
}

8
global.json

@ -1,17 +1,17 @@
{
"sdk": {
"version": "10.0.302",
"version": "10.0.400",
"allowPrerelease": true,
"rollForward": "major"
},
"tools": {
"dotnet": "10.0.302",
"dotnet": "10.0.400",
"runtimes": {
"aspnetcore": [
"8.0.29",
"9.0.18"
"8.0.30",
"9.0.19"
]
}
},

1
sandbox/OpenIddict.Sandbox.AspNet.Client/OpenIddict.Sandbox.AspNet.Client.csproj

@ -15,7 +15,6 @@
<ItemGroup>
<ProjectReference Include="..\..\src\OpenIddict.EntityFramework\OpenIddict.EntityFramework.csproj" />
<ProjectReference Include="..\..\src\OpenIddict.Quartz\OpenIddict.Quartz.csproj" />
<ProjectReference Include="..\..\src\OpenIddict.Owin\OpenIddict.Owin.csproj" />
</ItemGroup>

2
sandbox/OpenIddict.Sandbox.AspNetCore.Client/OpenIddict.Sandbox.AspNetCore.Client.csproj

@ -12,7 +12,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
<PackageReference Include="Quartz.Extensions.Hosting" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' ">
@ -26,6 +25,7 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Core" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" />
<PackageReference Include="Quartz.Extensions.Hosting" />
</ItemGroup>
</Project>

2
sandbox/OpenIddict.Sandbox.AspNetCore.Server/OpenIddict.Sandbox.AspNetCore.Server.csproj

@ -15,7 +15,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
<PackageReference Include="Quartz.Extensions.Hosting" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' ">
@ -29,6 +28,7 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Core" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" />
<PackageReference Include="Quartz.Extensions.Hosting" />
</ItemGroup>
</Project>

7
src/OpenIddict.Quartz/OpenIddict.Quartz.csproj

@ -18,6 +18,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Quartz" />
</ItemGroup>
<ItemGroup
Condition=" ('$(TargetFrameworkIdentifier)' == '.NETFramework') Or
('$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '10.0'))) Or
('$(TargetFrameworkIdentifier)' == '.NETStandard') ">
<PackageReference Include="Quartz.Extensions.DependencyInjection" />
</ItemGroup>

27
src/OpenIddict.Quartz/OpenIddictQuartzConfiguration.cs

@ -14,7 +14,7 @@ namespace OpenIddict.Quartz;
/// Contains the methods required to ensure that the OpenIddict Quartz.NET configuration is valid.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public sealed class OpenIddictQuartzConfiguration : IConfigureOptions<QuartzOptions>, IPostConfigureOptions<OpenIddictQuartzOptions>
public sealed class OpenIddictQuartzConfiguration : IPostConfigureOptions<OpenIddictQuartzOptions>
{
private readonly IServiceProvider _provider;
@ -25,31 +25,6 @@ public sealed class OpenIddictQuartzConfiguration : IConfigureOptions<QuartzOpti
public OpenIddictQuartzConfiguration(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <inheritdoc/>
public void Configure(QuartzOptions options)
{
ArgumentNullException.ThrowIfNull(options);
options.AddJob<OpenIddictQuartzJob>(builder =>
{
builder.StoreDurably()
.WithIdentity(OpenIddictQuartzJob.Identity)
.WithDescription(SR.GetResourceString(SR.ID8001));
});
options.AddTrigger(builder =>
{
// Note: this trigger uses a quite long interval (1 hour), which means it may be potentially never
// reached if the application is shut down or recycled. As such, this trigger is set up to fire
// between 1 and 10 minutes after the application starts to ensure the job is executed at least once.
builder.ForJob(OpenIddictQuartzJob.Identity)
.WithIdentity(SR.GetResourceString(SR.ID8004), SR.GetResourceString(SR.ID8005))
.WithSimpleSchedule(options => options.WithIntervalInHours(1).RepeatForever())
.WithDescription(SR.GetResourceString(SR.ID8002))
.StartAt(DateBuilder.FutureDate(new Random().Next(1, 10), IntervalUnit.Minute));
});
}
/// <inheritdoc/>
public void PostConfigure(string? name, OpenIddictQuartzOptions options)
{

36
src/OpenIddict.Quartz/OpenIddictQuartzExtensions.cs

@ -25,16 +25,38 @@ public static class OpenIddictQuartzExtensions
{
ArgumentNullException.ThrowIfNull(builder);
builder.Services.AddQuartz();
// Note: the AddQuartz() method MUST only be called once to avoid adding multiple jobs and triggers.
if (!builder.Services.Any(static descriptor => descriptor.ServiceType == typeof(OpenIddictQuartzJob)))
{
builder.Services.AddQuartz(options =>
{
options.AddJob<OpenIddictQuartzJob>(static builder =>
{
builder.StoreDurably()
.WithIdentity(OpenIddictQuartzJob.Identity)
.WithDescription(SR.GetResourceString(SR.ID8001));
});
// The OpenIddict job is registered as a service to allow
// Quartz.NET's DI integration to resolve it from the DI.
builder.Services.TryAddTransient<OpenIddictQuartzJob>();
options.AddTrigger(static builder =>
{
// Note: this trigger uses a quite long interval (1 hour), which means it may be potentially never
// reached if the application is shut down or recycled. As such, this trigger is set up to fire
// between 1 and 10 minutes after the application starts to ensure the job is executed at least once.
builder.ForJob(OpenIddictQuartzJob.Identity)
.WithIdentity(SR.GetResourceString(SR.ID8004), SR.GetResourceString(SR.ID8005))
.WithSimpleSchedule(options => options.WithInterval(TimeSpan.FromHours(1)).RepeatForever())
.WithDescription(SR.GetResourceString(SR.ID8002))
.StartAt(TimeProvider.System.GetUtcNow() + TimeSpan.FromMinutes(new Random().Next(1, 10)));
});
});
}
// Note: TryAddEnumerable() is used here to ensure the initializers are registered only once.
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<
IConfigureOptions<QuartzOptions>, OpenIddictQuartzConfiguration>());
#if !NET10_0_OR_GREATER
// Note: unlike Quartz.NET 4.0+, Quartz.NET 3.x doesn't automatically register the job as a service.
builder.Services.TryAddTransient<OpenIddictQuartzJob>();
#endif
// Note: TryAddEnumerable() is used here to ensure the initializer is registered only once.
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<
IPostConfigureOptions<OpenIddictQuartzOptions>, OpenIddictQuartzConfiguration>());

39
src/OpenIddict.Quartz/OpenIddictQuartzJob.cs

@ -16,24 +16,21 @@ namespace OpenIddict.Quartz;
[DisallowConcurrentExecution, EditorBrowsable(EditorBrowsableState.Advanced)]
public sealed class OpenIddictQuartzJob : IJob
{
private readonly IOptionsMonitor<OpenIddictQuartzOptions> _options;
private readonly IServiceProvider _provider;
#if !NET10_0_OR_GREATER
/// <summary>
/// Creates a new instance of the <see cref="OpenIddictQuartzJob"/> class.
/// </summary>
public OpenIddictQuartzJob() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0082));
#endif
/// <summary>
/// Creates a new instance of the <see cref="OpenIddictQuartzJob"/> class.
/// </summary>
/// <param name="options">The OpenIddict Quartz.NET options.</param>
/// <param name="provider">The service provider.</param>
public OpenIddictQuartzJob(IOptionsMonitor<OpenIddictQuartzOptions> options, IServiceProvider provider)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
public OpenIddictQuartzJob(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Gets the default identity assigned to this job.
@ -43,20 +40,24 @@ public sealed class OpenIddictQuartzJob : IJob
group: SR.GetResourceString(SR.ID8005));
/// <inheritdoc/>
#if NET10_0_OR_GREATER
public async ValueTask Execute(IJobExecutionContext context, CancellationToken cancellationToken = default)
#else
public async Task Execute(IJobExecutionContext context)
#endif
{
ArgumentNullException.ThrowIfNull(context);
List<Exception>? exceptions = null;
// Note: this job is registered as a transient service. As such, it cannot directly depend on scoped services
// like the core managers. To work around this limitation, a scope is manually created for each invocation.
await using var scope = _provider.CreateAsyncScope();
var options = scope.ServiceProvider.GetRequiredService<IOptionsMonitor<OpenIddictQuartzOptions>>().CurrentValue;
// Important: since authorizations that still have tokens attached are never
// pruned, the tokens MUST be deleted before deleting the authorizations.
if (!_options.CurrentValue.DisableTokenPruning)
if (!options.DisableTokenPruning)
{
var manager = scope.ServiceProvider.GetService<IOpenIddictTokenManager>() ??
throw new JobExecutionException(new InvalidOperationException(SR.GetResourceString(SR.ID0278)))
@ -66,7 +67,7 @@ public sealed class OpenIddictQuartzJob : IJob
UnscheduleFiringTrigger = true
};
var threshold = _options.CurrentValue.TimeProvider.GetUtcNow() - _options.CurrentValue.MinimumTokenLifespan;
var threshold = options.TimeProvider.GetUtcNow() - options.MinimumTokenLifespan;
try
{
@ -88,7 +89,7 @@ public sealed class OpenIddictQuartzJob : IJob
// occurred while trying to prune the entities. In this case, add the inner exceptions to the collection.
catch (AggregateException exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: exception.InnerExceptions.Count);
exceptions.AddRange(exception.InnerExceptions);
}
@ -96,12 +97,12 @@ public sealed class OpenIddictQuartzJob : IJob
// to be re-thrown later (typically, at the very end of this job, as an AggregateException).
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
}
}
if (!_options.CurrentValue.DisableAuthorizationPruning)
if (!options.DisableAuthorizationPruning)
{
var manager = scope.ServiceProvider.GetService<IOpenIddictAuthorizationManager>() ??
throw new JobExecutionException(new InvalidOperationException(SR.GetResourceString(SR.ID0278)))
@ -111,7 +112,7 @@ public sealed class OpenIddictQuartzJob : IJob
UnscheduleFiringTrigger = true
};
var threshold = _options.CurrentValue.TimeProvider.GetUtcNow() - _options.CurrentValue.MinimumAuthorizationLifespan;
var threshold = options.TimeProvider.GetUtcNow() - options.MinimumAuthorizationLifespan;
try
{
@ -133,7 +134,7 @@ public sealed class OpenIddictQuartzJob : IJob
// occurred while trying to prune the entities. In this case, add the inner exceptions to the collection.
catch (AggregateException exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: exception.InnerExceptions.Count);
exceptions.AddRange(exception.InnerExceptions);
}
@ -141,17 +142,17 @@ public sealed class OpenIddictQuartzJob : IJob
// to be re-thrown later (typically, at the very end of this job, as an AggregateException).
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
}
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new JobExecutionException(new AggregateException(exceptions))
{
// Only refire the job if the maximum refire count set in the options wasn't reached.
RefireImmediately = context.RefireCount < _options.CurrentValue.MaximumRefireCount
RefireImmediately = context.RefireCount < options.MaximumRefireCount
};
}
}

44
test/OpenIddict.Quartz.Tests/OpenIddictQuartzConfigurationTests.cs

@ -1,44 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Xunit;
namespace OpenIddict.Quartz.Tests;
public class OpenIddictQuartzConfigurationTests
{
[Fact]
public void UseQuartz_RegistersJobDetails()
{
// Arrange
var options = new QuartzOptions();
var configuration = new OpenIddictQuartzConfiguration(new ServiceCollection().BuildServiceProvider());
// Act
configuration.Configure(options);
// Assert
Assert.Single(options.JobDetails);
Assert.Equal(OpenIddictQuartzJob.Identity, options.JobDetails[0].Key);
Assert.Equal(SR.GetResourceString(SR.ID8003), options.JobDetails[0].Key.Name);
Assert.Equal(SR.GetResourceString(SR.ID8005), options.JobDetails[0].Key.Group);
Assert.Equal(SR.GetResourceString(SR.ID8001), options.JobDetails[0].Description);
}
[Fact]
public void UseQuartz_RegistersTriggerDetails()
{
// Arrange
var options = new QuartzOptions();
var configuration = new OpenIddictQuartzConfiguration(new ServiceCollection().BuildServiceProvider());
// Act
configuration.Configure(options);
// Assert
Assert.Single(options.Triggers);
Assert.Equal(OpenIddictQuartzJob.Identity, options.Triggers[0].JobKey);
Assert.Equal(SR.GetResourceString(SR.ID8004), options.Triggers[0].Key.Name);
Assert.Equal(SR.GetResourceString(SR.ID8005), options.Triggers[0].Key.Group);
Assert.Equal(SR.GetResourceString(SR.ID8002), options.Triggers[0].Description);
}
}

17
test/OpenIddict.Quartz.Tests/OpenIddictQuartzExtensionsTests.cs

@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Quartz;
using Xunit;
namespace OpenIddict.Quartz.Tests;
@ -43,9 +42,15 @@ public class OpenIddictQuartzExtensionsTests
builder.UseQuartz();
// Assert
#if NET10_0_OR_GREATER
Assert.Contains(services, service => service.ServiceType == typeof(OpenIddictQuartzJob) &&
service.ImplementationType == typeof(OpenIddictQuartzJob) &&
service.Lifetime == ServiceLifetime.Transient);
service.Lifetime is ServiceLifetime.Scoped);
#else
Assert.Contains(services, service => service.ServiceType == typeof(OpenIddictQuartzJob) &&
service.ImplementationType == typeof(OpenIddictQuartzJob) &&
service.Lifetime is ServiceLifetime.Transient);
#endif
}
[Fact]
@ -62,11 +67,9 @@ public class OpenIddictQuartzExtensionsTests
// Assert
Assert.Single(services, service => service.ServiceType == typeof(OpenIddictQuartzJob) &&
service.ImplementationType == typeof(OpenIddictQuartzJob) &&
service.Lifetime == ServiceLifetime.Transient);
service.ImplementationType == typeof(OpenIddictQuartzJob));
Assert.Single(services, service => service.ServiceType == typeof(IConfigureOptions<QuartzOptions>) &&
service.ImplementationType == typeof(OpenIddictQuartzConfiguration) &&
service.Lifetime == ServiceLifetime.Singleton);
Assert.Single(services, service => service.ServiceType == typeof(IPostConfigureOptions<OpenIddictQuartzOptions>) &&
service.ImplementationType == typeof(OpenIddictQuartzConfiguration));
}
}

161
test/OpenIddict.Quartz.Tests/OpenIddictQuartzJobTests.cs

@ -8,33 +8,36 @@ namespace OpenIddict.Quartz.Tests;
public class OpenIddictQuartzJobTests
{
#if !NET10_0_OR_GREATER
[Fact]
public void Constructor_ThrowsAnException()
public void Constructor_ThrowsAnExceptionWhenServiceProviderCannotBeResolved()
{
// Arrange, act and assert
var exception = Assert.Throws<InvalidOperationException>(() => new OpenIddictQuartzJob());
Assert.Equal(SR.GetResourceString(SR.ID0082), exception.Message);
}
#endif
[Fact]
public async Task Execute_UsesServiceScope()
{
// Arrange
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == Mock.Of<IOpenIddictAuthorizationManager>() &&
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>());
var scope = Mock.Of<IServiceScope>(scope => scope.ServiceProvider == provider);
var factory = Mock.Of<IServiceScopeFactory>(factory => factory.CreateScope() == scope);
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var job = new OpenIddictQuartzJob(monitor,
Mock.Of<IServiceProvider>(provider => provider.GetService(typeof(IServiceScopeFactory)) == factory));
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == Mock.Of<IOpenIddictAuthorizationManager>() &&
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>() &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var scope = Mock.Of<IServiceScope>(scope => scope.ServiceProvider == provider);
var factory = Mock.Of<IServiceScopeFactory>(factory => factory.CreateScope() == scope);
var job = new OpenIddictQuartzJob(Mock.Of<IServiceProvider>(provider => provider.GetService(typeof(IServiceScopeFactory)) == factory));
// Act
await job.Execute(Mock.Of<IJobExecutionContext>());
@ -47,14 +50,21 @@ public class OpenIddictQuartzJobTests
public async Task Execute_IgnoresPruningWhenTokenPruningIsDisabled()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
DisableTokenPruning = true,
TimeProvider = TimeProvider.System
});
var manager = new Mock<IOpenIddictAuthorizationManager>();
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == Mock.Of<IOpenIddictAuthorizationManager>() &&
provider.GetService(typeof(IOpenIddictTokenManager)) == manager.Object);
provider.GetService(typeof(IOpenIddictTokenManager)) == manager.Object &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var job = CreateJob(provider, options => options.DisableTokenPruning = true);
var job = CreateJob(provider);
// Act
await job.Execute(Mock.Of<IJobExecutionContext>());
@ -67,14 +77,21 @@ public class OpenIddictQuartzJobTests
public async Task Execute_IgnoresPruningWhenAuthorizationPruningIsDisabled()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
DisableAuthorizationPruning = true,
TimeProvider = TimeProvider.System
});
var manager = new Mock<IOpenIddictAuthorizationManager>();
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == manager.Object &&
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>());
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>() &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var job = CreateJob(provider, options => options.DisableAuthorizationPruning = true);
var job = CreateJob(provider);
// Act
await job.Execute(Mock.Of<IJobExecutionContext>());
@ -87,14 +104,22 @@ public class OpenIddictQuartzJobTests
public async Task Execute_UnschedulesTriggersWhenTokenManagerIsMissing()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == Mock.Of<IOpenIddictAuthorizationManager>() &&
provider.GetService(typeof(IOpenIddictTokenManager)) == null);
provider.GetService(typeof(IOpenIddictTokenManager)) == null &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var job = CreateJob(provider);
// Act and assert
var exception = await Assert.ThrowsAsync<JobExecutionException>(() => job.Execute(Mock.Of<IJobExecutionContext>()));
var exception = await Assert.ThrowsAsync<JobExecutionException>(async () =>
await job.Execute(Mock.Of<IJobExecutionContext>()));
Assert.False(exception.RefireImmediately);
Assert.True(exception.UnscheduleAllTriggers);
@ -108,13 +133,21 @@ public class OpenIddictQuartzJobTests
public async Task Execute_UnschedulesTriggersWhenAuthorizationManagerIsMissing()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == null);
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == null &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var job = CreateJob(provider);
// Act and assert
var exception = await Assert.ThrowsAsync<JobExecutionException>(() => job.Execute(Mock.Of<IJobExecutionContext>()));
var exception = await Assert.ThrowsAsync<JobExecutionException>(async () =>
await job.Execute(Mock.Of<IJobExecutionContext>()));
Assert.False(exception.RefireImmediately);
Assert.True(exception.UnscheduleAllTriggers);
@ -128,36 +161,50 @@ public class OpenIddictQuartzJobTests
public async Task Execute_RethrowsOutOfMemoryExceptionsThrownDuringTokenPruning()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var manager = new Mock<IOpenIddictTokenManager>();
manager.Setup(manager => manager.PruneAsync(It.IsAny<DateTimeOffset>(), It.IsAny<CancellationToken>()))
.Throws(new OutOfMemoryException());
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == Mock.Of<IOpenIddictAuthorizationManager>() &&
provider.GetService(typeof(IOpenIddictTokenManager)) == manager.Object);
provider.GetService(typeof(IOpenIddictTokenManager)) == manager.Object &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var job = CreateJob(provider);
// Act and assert
await Assert.ThrowsAsync<OutOfMemoryException>(() => job.Execute(Mock.Of<IJobExecutionContext>()));
await Assert.ThrowsAsync<OutOfMemoryException>(async () => await job.Execute(Mock.Of<IJobExecutionContext>()));
}
[Fact]
public async Task Execute_RethrowsOutOfMemoryExceptionsThrownDuringAuthorizationPruning()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var manager = new Mock<IOpenIddictAuthorizationManager>();
manager.Setup(manager => manager.PruneAsync(It.IsAny<DateTimeOffset>(), It.IsAny<CancellationToken>()))
.Throws(new OutOfMemoryException());
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == manager.Object &&
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>());
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>() &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var job = CreateJob(provider);
// Act and assert
await Assert.ThrowsAsync<OutOfMemoryException>(() => job.Execute(Mock.Of<IJobExecutionContext>()));
await Assert.ThrowsAsync<OutOfMemoryException>(async () => await job.Execute(Mock.Of<IJobExecutionContext>()));
}
[Fact]
@ -166,20 +213,27 @@ public class OpenIddictQuartzJobTests
// Arrange
var token = new CancellationToken(canceled: true);
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var manager = new Mock<IOpenIddictTokenManager>();
manager.Setup(manager => manager.PruneAsync(It.IsAny<DateTimeOffset>(), It.IsAny<CancellationToken>()))
.Throws(new OperationCanceledException(token));
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == Mock.Of<IOpenIddictAuthorizationManager>() &&
provider.GetService(typeof(IOpenIddictTokenManager)) == manager.Object);
provider.GetService(typeof(IOpenIddictTokenManager)) == manager.Object &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var context = Mock.Of<IJobExecutionContext>(context => context.CancellationToken == token);
var job = CreateJob(provider);
// Act and assert
var exception = await Assert.ThrowsAsync<JobExecutionException>(() => job.Execute(context));
var exception = await Assert.ThrowsAsync<JobExecutionException>(async () => await job.Execute(context));
Assert.False(exception.RefireImmediately);
@ -192,20 +246,27 @@ public class OpenIddictQuartzJobTests
// Arrange
var token = new CancellationToken(canceled: true);
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var manager = new Mock<IOpenIddictAuthorizationManager>();
manager.Setup(manager => manager.PruneAsync(It.IsAny<DateTimeOffset>(), It.IsAny<CancellationToken>()))
.Throws(new OperationCanceledException(token));
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == manager.Object &&
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>());
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>() &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var context = Mock.Of<IJobExecutionContext>(context => context.CancellationToken == token);
var job = CreateJob(provider);
// Act and assert
var exception = await Assert.ThrowsAsync<JobExecutionException>(() => job.Execute(context));
var exception = await Assert.ThrowsAsync<JobExecutionException>(async () => await job.Execute(context));
Assert.False(exception.RefireImmediately);
@ -216,6 +277,12 @@ public class OpenIddictQuartzJobTests
public async Task Execute_AllowsRefiringWhenExceptionsAreThrown()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var provider = new Mock<IServiceProvider>();
provider.Setup(provider => provider.GetService(typeof(IOpenIddictAuthorizationManager)))
.Returns(CreateAuthorizationManager(new ApplicationException()));
@ -223,12 +290,15 @@ public class OpenIddictQuartzJobTests
provider.Setup(provider => provider.GetService(typeof(IOpenIddictTokenManager)))
.Returns(CreateTokenManager(new ApplicationException()));
provider.Setup(provider => provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)))
.Returns(monitor);
var context = Mock.Of<IJobExecutionContext>(context => context.RefireCount == 0);
var job = CreateJob(provider.Object);
// Act and assert
var exception = await Assert.ThrowsAsync<JobExecutionException>(() => job.Execute(context));
var exception = await Assert.ThrowsAsync<JobExecutionException>(async () => await job.Execute(context));
Assert.True(exception.RefireImmediately);
Assert.IsType<AggregateException>(exception.InnerException);
@ -259,6 +329,12 @@ public class OpenIddictQuartzJobTests
public async Task Execute_AllowsRefiringWhenAggregateExceptionsAreThrown()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
});
var provider = new Mock<IServiceProvider>();
provider.Setup(provider => provider.GetService(typeof(IOpenIddictAuthorizationManager)))
.Returns(CreateAuthorizationManager(new AggregateException(
@ -268,12 +344,15 @@ public class OpenIddictQuartzJobTests
.Returns(CreateTokenManager(new AggregateException(
new InvalidOperationException(), new ApplicationException())));
provider.Setup(provider => provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)))
.Returns(monitor);
var context = Mock.Of<IJobExecutionContext>(context => context.RefireCount == 0);
var job = CreateJob(provider.Object);
// Act and assert
var exception = await Assert.ThrowsAsync<JobExecutionException>(() => job.Execute(context));
var exception = await Assert.ThrowsAsync<JobExecutionException>(async () => await job.Execute(context));
Assert.True(exception.RefireImmediately);
Assert.IsType<AggregateException>(exception.InnerException);
@ -306,38 +385,38 @@ public class OpenIddictQuartzJobTests
public async Task Execute_DisallowsRefiringWhenMaximumRefireCountIsReached()
{
// Arrange
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(
monitor => monitor.CurrentValue == new OpenIddictQuartzOptions
{
MaximumRefireCount = 5,
TimeProvider = TimeProvider.System
});
var manager = new Mock<IOpenIddictAuthorizationManager>();
manager.Setup(manager => manager.PruneAsync(It.IsAny<DateTimeOffset>(), It.IsAny<CancellationToken>()))
.Throws(new ApplicationException());
var provider = Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IOpenIddictAuthorizationManager)) == manager.Object &&
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>());
provider.GetService(typeof(IOpenIddictTokenManager)) == Mock.Of<IOpenIddictTokenManager>() &&
provider.GetService(typeof(IOptionsMonitor<OpenIddictQuartzOptions>)) == monitor);
var context = Mock.Of<IJobExecutionContext>(context => context.RefireCount == 5);
var job = CreateJob(provider, options => options.MaximumRefireCount = 5);
var job = CreateJob(provider);
// Act and assert
var exception = await Assert.ThrowsAsync<JobExecutionException>(() => job.Execute(context));
var exception = await Assert.ThrowsAsync<JobExecutionException>(async () => await job.Execute(context));
Assert.False(exception.RefireImmediately);
}
private static OpenIddictQuartzJob CreateJob(IServiceProvider provider, Action<OpenIddictQuartzOptions>? configuration = null)
private static OpenIddictQuartzJob CreateJob(IServiceProvider provider)
{
var scope = Mock.Of<IServiceScope>(scope => scope.ServiceProvider == provider);
var factory = Mock.Of<IServiceScopeFactory>(factory => factory.CreateScope() == scope);
var options = new OpenIddictQuartzOptions
{
TimeProvider = TimeProvider.System
};
configuration?.Invoke(options);
var monitor = Mock.Of<IOptionsMonitor<OpenIddictQuartzOptions>>(monitor => monitor.CurrentValue == options);
return new OpenIddictQuartzJob(monitor,
Mock.Of<IServiceProvider>(provider => provider.GetService(typeof(IServiceScopeFactory)) == factory));
return new OpenIddictQuartzJob(Mock.Of<IServiceProvider>(provider =>
provider.GetService(typeof(IServiceScopeFactory)) == factory));
}
}

Loading…
Cancel
Save