From 54edcd955b3d2eb74fbe4756f74b6d365ccefc58 Mon Sep 17 00:00:00 2001 From: CDR-AidenJ Date: Wed, 7 Oct 2026 16:04:45 +1100 Subject: [PATCH] v3.2.0 release (#34) Co-authored-by: CDR Open Source --- .azuredevops/pipelines/build-dr-func-v2.yml | 4 +- .azuredevops/pipelines/build-dr-func.yml | 4 +- .azuredevops/pipelines/build-v2.yml | 12 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/sonarcloud-analysis.yml | 2 +- CHANGELOG.md | 10 + Help/azurefunctions/HELP.md | 2 +- Help/debugging/HELP.md | 4 +- Help/testing/HELP.md | 4 +- README.md | 10 +- .../RequestResponseLoggingMiddleware.cs | 6 +- Source/CdrAuthServer.E2ETests/BaseTest.cs | 5 +- .../CdrAuthServer.E2ETests.csproj | 3 + .../US39327_CdrAuthServer_E2ETests.cs | 6 +- .../XUnit/Orderers/AlphabeticalOrderer.cs | 22 +- .../appsettings.Development.json | 2 +- .../appsettings.Release.json | 2 +- .../BaseTest.cs | 3 +- ....GetDataRecipients.IntegrationTests.csproj | 5 +- .../DisplayTestMethodNameAttribute.cs | 7 +- .../Fixtures/TestFixture.cs | 10 +- .../XUnit/AlphabeticalOrderer.cs | 22 +- .../GetDataRecipientsFunction.cs | 2 +- .../CdrAuthServer.Infrastructure.csproj | 2 +- .../Certificates/CertificateLoader.cs | 4 +- .../Configuration/ConfigureSwaggerOptions.cs | 4 +- .../CdrSwaggerMiddlewareExtensions.cs | 4 +- .../Extensions/HttpExtensions.cs | 2 +- .../Models/CdrApiOptions.cs | 5 +- .../PrivateKeyJwt.cs | 2 +- .../Versioning/ApiVersionErrorResponse.cs | 50 -- .../Versioning/CdrVersionReader.cs | 18 +- .../BaseTest.cs | 7 +- .../CdrAuthServer.IntegrationTests.csproj | 4 +- .../US44264_CdrAuthServer_JARM_Authorise.cs | 4 +- .../JARM/US44264_CdrAuthServer_JARM_DCR.cs | 2 +- .../JARM/US44264_CdrAuthServer_JARM_PAR.cs | 2 +- .../US12678_CdrAuthServer_Authorisation.cs | 53 +- ...S12962_CdrAuthServer_OIDC_Configuration.cs | 2 +- .../Tests/US12963_CdrAuthServer_Token.cs | 6 +- .../Tests/US12964_CDRAuthServer_OIDC_JWKS.cs | 2 +- .../US12966_CdrAuthServer_Introspection.cs | 10 +- .../Tests/US12968_CdrAuthServer_PAR.cs | 6 +- ...US15584_CdrAuthServer_Registration_POST.cs | 4 +- .../US18469_CdrAuthServer_TokenRevocation.cs | 6 +- .../XUnit/Orderers/AlphabeticalOrderer.cs | 24 +- .../XUnit/Skippable/Samples.cs | 57 --- .../XUnit/Skippable/SkipTestException.cs | 12 - .../XUnit/Skippable/SkippableFactAttribute.cs | 10 - .../Skippable/SkippableTheoryAttribute.cs | 10 - .../SkippableFactDiscoverer.cs | 21 - .../SkippableFactMessageBus.cs | 39 -- .../XunitExtensions/SkippableFactTestCase.cs | 40 -- .../SkippableTheoryDiscoverer.cs | 33 -- .../SkippableTheoryTestCase.cs | 42 -- .../XUnit/Skippable/readme.md | 3 - .../appsettings.Development.json | 2 +- .../appsettings.Release.json | 2 +- .../Configuration/GrantConfiguration.cs | 14 +- ...SeedDataWithDeterministicDates.Designer.cs | 261 ++++++++++ ...dateGrantSeedDataWithDeterministicDates.cs | 61 +++ ...AuthServervDatabaseContextModelSnapshot.cs | 65 +-- Source/CdrAuthServer.UI/.nvmrc | 1 + Source/CdrAuthServer.UI/package-lock.json | 454 +++++++----------- Source/CdrAuthServer.UI/package.json | 4 + Source/CdrAuthServer.UnitTests/BaseTest.cs | 4 +- .../Controllers/UtilityControllerTests.cs | 6 +- .../Helpers/HttpHelperTests.cs | 25 +- .../CdrAuthServer.UnitTests/ResultHelper.cs | 2 +- .../Services/ConsentRevocationServiceTests.cs | 31 +- .../Services/RegisterClientServiceTests.cs | 2 +- .../ClientAssertionValidatorTests.cs | 2 +- .../Certificates/CertificateValidator.cs | 2 +- Source/CdrAuthServer.sln | 119 ----- Source/CdrAuthServer.slnx | 35 ++ Source/CdrAuthServer/CdrAuthServer.csproj | 1 + .../Controllers/AdminController.cs | 3 +- .../ArrangementRevocationController.cs | 3 +- .../Controllers/AuthorisationController.cs | 1 + .../Controllers/DiscoveryController.cs | 3 +- .../Controllers/IntrospectionController.cs | 1 + .../Controllers/JwksController.cs | 1 + .../PushedAuthorisationController.cs | 3 +- .../Controllers/RegistrationController.cs | 1 + .../Controllers/ResourceController.cs | 3 +- .../Controllers/RevocationController.cs | 1 + .../Controllers/TokenController.cs | 3 +- .../Controllers/UserInfoController.cs | 3 +- .../Controllers/UtilityController.cs | 1 + .../Extensions/SwaggerExtensions.cs | 16 +- .../IdPermanence/IdPermanenceHelper.cs | 2 +- Source/CdrAuthServer/Program.cs | 4 +- .../Services/ConsentRevocationService.cs | 2 +- Source/CdrAuthServer/Services/TokenService.cs | 2 +- .../Validation/ValidateMtlsAttribute.cs | 2 +- Source/CdrAuthServer_Shared.sln | 151 ------ Source/CdrAuthServer_Shared.slnx | 64 +++ Source/Directory.Build.props | 6 +- Source/Directory.Packages.props | 76 +-- Source/Dockerfile | 15 +- Source/Dockerfile.e2e-tests | 5 +- Source/Dockerfile.get-data-recipients | 8 +- ...file.get-data-recipients.integration-tests | 2 +- Source/Dockerfile.integration-tests | 2 +- Source/Dockerfile.standalone | 43 +- Source/Dockerfile.unit-tests | 8 +- Source/supervisord.standalone.conf | 11 +- 107 files changed, 963 insertions(+), 1215 deletions(-) delete mode 100644 Source/CdrAuthServer.Infrastructure/Versioning/ApiVersionErrorResponse.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/Samples.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkipTestException.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkippableFactAttribute.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkippableTheoryAttribute.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactDiscoverer.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactMessageBus.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactTestCase.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableTheoryDiscoverer.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableTheoryTestCase.cs delete mode 100644 Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/readme.md create mode 100644 Source/CdrAuthServer.Repository/Migrations/20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates.Designer.cs create mode 100644 Source/CdrAuthServer.Repository/Migrations/20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates.cs create mode 100644 Source/CdrAuthServer.UI/.nvmrc delete mode 100644 Source/CdrAuthServer.sln create mode 100644 Source/CdrAuthServer.slnx delete mode 100644 Source/CdrAuthServer_Shared.sln create mode 100644 Source/CdrAuthServer_Shared.slnx diff --git a/.azuredevops/pipelines/build-dr-func-v2.yml b/.azuredevops/pipelines/build-dr-func-v2.yml index b9590b7..cf39ce5 100644 --- a/.azuredevops/pipelines/build-dr-func-v2.yml +++ b/.azuredevops/pipelines/build-dr-func-v2.yml @@ -159,10 +159,10 @@ steps: # Tests have passed, so now build/publish the azure function - task: UseDotNet@2 - displayName: 'Install .NET 8 SDK' + displayName: 'Install .NET 10 SDK' inputs: packageType: 'sdk' - version: '8.0.x' + version: '10.0.x' performMultiLevelLookup: true - script: | diff --git a/.azuredevops/pipelines/build-dr-func.yml b/.azuredevops/pipelines/build-dr-func.yml index e30037c..fd31c0b 100644 --- a/.azuredevops/pipelines/build-dr-func.yml +++ b/.azuredevops/pipelines/build-dr-func.yml @@ -13,10 +13,10 @@ pool: steps: - task: UseDotNet@2 - displayName: 'Install .NET 8 SDK' + displayName: 'Install .NET 10 SDK' inputs: packageType: 'sdk' - version: '8.0.x' + version: '10.0.x' performMultiLevelLookup: true - script: | diff --git a/.azuredevops/pipelines/build-v2.yml b/.azuredevops/pipelines/build-v2.yml index fdb7814..ee64c3e 100644 --- a/.azuredevops/pipelines/build-v2.yml +++ b/.azuredevops/pipelines/build-v2.yml @@ -307,6 +307,12 @@ jobs: docker compose --file $(baseSourceDirectory)/docker-compose.E2ETests.Standalone.yml down displayName: 'E2E Tests (Standalone) - Down' condition: always() + + - task: UseDotNet@2 + displayName: 'Install .NET 8 Runtime for TrxToExtentReport' + inputs: + packageType: 'runtime' + version: '8.0.x' # Run trx formatter to output .MD and .CSV - script: | @@ -389,18 +395,18 @@ jobs: ################################################################################################### - task: UseDotNet@2 - displayName: "Use .NET 8 sdk" + displayName: "Use .NET 10 sdk" condition: always() inputs: packageType: sdk - version: "8.0.x" + version: "10.0.x" performMultiLevelLookup: true - task: CmdLine@2 displayName: "Install dotnet-ef" condition: always() inputs: - script: "dotnet tool install --version 8.0.4 --global dotnet-ef" + script: "dotnet tool install --version 10.0.10 --global dotnet-ef" - task: CmdLine@2 displayName: "Check dotnet-ef version" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cef68d4..288d036 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -69,7 +69,7 @@ jobs: - name: Build solution run: | - dotnet build ./Source/CdrAuthServer.sln --configuration 'Release' + dotnet build ./Source/CdrAuthServer.slnx --configuration 'Release' - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/sonarcloud-analysis.yml b/.github/workflows/sonarcloud-analysis.yml index f73836b..fbb5281 100644 --- a/.github/workflows/sonarcloud-analysis.yml +++ b/.github/workflows/sonarcloud-analysis.yml @@ -70,5 +70,5 @@ jobs: shell: powershell run: | .\.sonar\scanner\dotnet-sonarscanner begin /k:"ConsumerDataRight_authorisation-server" /o:"consumerdataright" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" - dotnet build .\source\CdrAuthServer.sln + dotnet build .\source\CdrAuthServer.slnx .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 32b29fe..d7cf921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [3.2.0] - 2026-09-30 +### Fixed +- Updated NuGet packages + +### Changed +- Updated to use .NET 10 version of ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation +- Migrated from .NET 8 to .NET 10 +- Migrated from SLN to SLNX + ## [3.1.0] - 2026-06-01 ### Changed - Migrated CDR Auth Server Standalone (CdrAuthServer.UI) from CRA to Vite diff --git a/Help/azurefunctions/HELP.md b/Help/azurefunctions/HELP.md index 54f70ae..48cba3b 100644 --- a/Help/azurefunctions/HELP.md +++ b/Help/azurefunctions/HELP.md @@ -62,5 +62,5 @@ SELECT * FROM [cdr-auth-server].[dbo].[LogEvents-DrService]

To Build Azure Functions

- dotnet SDK 8.0.10x or higher is required. Latest SDK can be found from the link https://microsoft.com/net + dotnet SDK 10.0.x or higher is required. Latest SDK can be found from the link https://microsoft.com/net
\ No newline at end of file diff --git a/Help/debugging/HELP.md b/Help/debugging/HELP.md index 950cdc5..828ea44 100644 --- a/Help/debugging/HELP.md +++ b/Help/debugging/HELP.md @@ -33,8 +33,8 @@ Authentication: Windows Authentication ### Start the Authorisation Server There are two Visual Studio solution files that are available for use: -- CdrAuthServer.sln - This is the default solution file that is used primarily for running and debugging the Authorisation Server projects. -- CdrAuthServer_Shared.sln - In addition to the Authorisation Server projects, this solution file also opens the [Mock Solutions Test Automation](https://github.com/ConsumerDataRight/mock-solution-test-automation) project. This is useful when wanting to debug or step through source code used in Mock Solution Test Automation project. Further information can be found in [Authorisation Server Test Automation Execution Guide](../testing/HELP.md) +- CdrAuthServer.slnx - This is the default solution file that is used primarily for running and debugging the Authorisation Server projects. +- CdrAuthServer_Shared.slnx - In addition to the Authorisation Server projects, this solution file also opens the [Mock Solutions Test Automation](https://github.com/ConsumerDataRight/mock-solution-test-automation) project. This is useful when wanting to debug or step through source code used in Mock Solution Test Automation project. Further information can be found in [Authorisation Server Test Automation Execution Guide](../testing/HELP.md) To launch the application using MS Visual Studio, the following projects need to be started: ``` diff --git a/Help/testing/HELP.md b/Help/testing/HELP.md index 37e23c8..740d85c 100644 --- a/Help/testing/HELP.md +++ b/Help/testing/HELP.md @@ -169,7 +169,7 @@ Tests can now be run using Microsoft Visual Studio. The following steps detail the process of running tests using Microsoft Visual Studio's Test Explorer: -1. Open the [CdrAuthServer.sln](../../Source/CdrAuthServer.sln) solution file in Microsoft Visual Studio. +1. Open the [CdrAuthServer.slnx](../../Source/CdrAuthServer.slnx) solution file in Microsoft Visual Studio. 2. Build the solution. 3. Open the Test Explorer. If Test Explorer is not visible, choose 'Test' on the Visual Studio menu and then choose 'Test Explorer'. @@ -191,7 +191,7 @@ This repository can be cloned using following command: git clone https://github.com/ConsumerDataRight/mock-solution-test-automation.git ``` -The [CdrAuthServer_Shared.sln](../../Source/CdrAuthServer_Shared.sln) solution has been created to allow for debugging and stepping through the source code used in Mock Solution Test Automation project. +The [CdrAuthServer_Shared.slnx](../../Source/CdrAuthServer_Shared.slnx) solution has been created to allow for debugging and stepping through the source code used in Mock Solution Test Automation project. [Authorisation Server Shared Solution in Microsoft Visual Studio](./images/MS-Visual-Studio-View-Cdr-Auth-Server-Shared-Solution.png) diff --git a/README.md b/README.md index 839e2a4..eb59d5d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![Consumer Data Right Logo](./Assets/cdr-logo.png?raw=true) -[![Consumer Data Standards v1.34.0](https://img.shields.io/badge/Consumer%20Data%20Standards-v1.34.0-blue.svg)](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.34.0/#introduction) -[![Conformance Test Suite Data Recipients 4.4.0](https://img.shields.io/badge/Conformance%20Test%20Suite%20Data%20Recipients-v4.4.0-darkblue.svg)](https://www.cdr.gov.au/for-providers/conformance-test-suite-data-recipients) +[![Consumer Data Standards v1.36.0](https://img.shields.io/badge/Consumer%20Data%20Standards-v1.36.0-blue.svg)](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.36.0/#introduction) +[![Conformance Test Suite Data Recipients 4.5.0](https://img.shields.io/badge/Conformance%20Test%20Suite%20Data%20Recipients-v4.5.0-darkblue.svg)](https://www.cdr.gov.au/for-providers/conformance-test-suite-data-recipients) [![FAPI 1.0 Advanced Profile](https://img.shields.io/badge/FAPI%201.0-orange.svg)](https://openid.net/specs/openid-financial-api-part-2-1_0.html) [![made-with-dotnet](https://img.shields.io/badge/Made%20with-.NET-1f425Ff.svg)](https://dotnet.microsoft.com/) [![made-with-csharp](https://img.shields.io/badge/Made%20with-C%23-1f425Ff.svg)](https://docs.microsoft.com/en-us/dotnet/csharp/) @@ -16,8 +16,8 @@ The project is used in the Participant Tooling Authorisation Server, providing t ## Authorisation Server - Alignment The Authorisation Server: -- aligns to [v1.34.0](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.34.0/#introduction) of the [Consumer Data Standards](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.34.0/#introduction) in particular [FAPI 1.0 Migration Phase 4](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.34.0/#introduction) with backwards compatibility to Migration Phase 2 and 3; -- has passed v4.4.0 of the [Conformance Test Suite for Data Recipients](https://www.cdr.gov.au/for-providers/conformance-test-suite-data-recipients); +- aligns to [v1.36.0](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.36.0/#introduction) of the [Consumer Data Standards](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.34.0/#introduction) in particular [FAPI 1.0 Migration Phase 4](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.36.0/#introduction) with backwards compatibility to Migration Phase 2 and 3; +- has passed v4.5.0 of the [Conformance Test Suite for Data Recipients](https://www.cdr.gov.au/for-providers/conformance-test-suite-data-recipients); and - is certified with the [FAPI 1.0 Advanced Profile](https://openid.net/specs/openid-financial-api-part-2-1_0.html) . @@ -146,7 +146,7 @@ The Authorisation Server contains the following components: ## Technology Stack The following technologies have been used to build the Authorisation Server: -- The source code has been written in `C#` using the `.Net 8` framework. +- The source code has been written in `C#` using the `.Net 10` framework. - The mTLS Gateway has been implemented using `Ocelot`. - The Repository utilises a `SQL` instance. - `xUnit` is the framework used for writing and running tests. diff --git a/Source/CdrAuthServer.API.Logger/RequestResponseLoggingMiddleware.cs b/Source/CdrAuthServer.API.Logger/RequestResponseLoggingMiddleware.cs index 4213413..18792b3 100644 --- a/Source/CdrAuthServer.API.Logger/RequestResponseLoggingMiddleware.cs +++ b/Source/CdrAuthServer.API.Logger/RequestResponseLoggingMiddleware.cs @@ -98,7 +98,7 @@ private async Task ExtractRequestProperties(HttpContext context) { context.Request.EnableBuffering(); await using var requestStream = _recyclableMemoryStreamManager.GetStream(); - await context.Request.Body.CopyToAsync(requestStream); + await context.Request.Body.CopyToAsync(requestStream, context.RequestAborted); _requestBody = ReadStreamInChunks(requestStream); context.Request.Body.Position = 0; @@ -289,7 +289,7 @@ private async Task ExtractResponseProperties(HttpContext httpContext) _elapsedTime = sw.ElapsedMilliseconds.ToString(); responseBody.Seek(0, SeekOrigin.Begin); - _responseBody = await new StreamReader(responseBody).ReadToEndAsync(); + _responseBody = await new StreamReader(responseBody).ReadToEndAsync(httpContext.RequestAborted); responseBody.Seek(0, SeekOrigin.Begin); IEnumerable keyValues = httpContext.Response.Headers.Keys.Select(key => key + ": " + string.Join(",", httpContext.Response.Headers[key].ToArray())); @@ -301,7 +301,7 @@ private async Task ExtractResponseProperties(HttpContext httpContext) // This is for middleware hooked before us to see our changes. // Otherwise the original stream would be seen which cannot be read again. - await responseBody.CopyToAsync(originalBodyStream); + await responseBody.CopyToAsync(originalBodyStream, httpContext.RequestAborted); } } diff --git a/Source/CdrAuthServer.E2ETests/BaseTest.cs b/Source/CdrAuthServer.E2ETests/BaseTest.cs index 8ffa65b..cd5af57 100644 --- a/Source/CdrAuthServer.E2ETests/BaseTest.cs +++ b/Source/CdrAuthServer.E2ETests/BaseTest.cs @@ -5,6 +5,7 @@ #undef TEST_DEBUG_MODE #endif +using CdrAuthServer.E2ETests.XUnit.Orderers; using ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation; using Microsoft.Extensions.Configuration; using Xunit; @@ -14,11 +15,11 @@ namespace CdrAuthServer.E2ETests { // Put all tests in same collection because we need them to run sequentially since some tests are mutating DB. [Collection("E2ETests")] - [TestCaseOrderer("CdrAuthServer.E2ETests.XUnit.Orderers.AlphabeticalOrderer", "CdrAuthServer.E2ETests")] + [TestCaseOrderer(typeof(AlphabeticalOrderer))] public abstract class BaseTest : SharedBaseTest { protected BaseTest(ITestOutputHelperAccessor testOutputHelperAccessor, IConfiguration config) - : base(testOutputHelperAccessor, config) + : base(config) { } } diff --git a/Source/CdrAuthServer.E2ETests/CdrAuthServer.E2ETests.csproj b/Source/CdrAuthServer.E2ETests/CdrAuthServer.E2ETests.csproj index 021dd91..69de89c 100644 --- a/Source/CdrAuthServer.E2ETests/CdrAuthServer.E2ETests.csproj +++ b/Source/CdrAuthServer.E2ETests/CdrAuthServer.E2ETests.csproj @@ -1,6 +1,7 @@  $(TargetFrameworkVersion) + Exe $(Version) $(Version) $(Version) @@ -35,6 +36,8 @@ + + true diff --git a/Source/CdrAuthServer.E2ETests/US39327_CdrAuthServer_E2ETests.cs b/Source/CdrAuthServer.E2ETests/US39327_CdrAuthServer_E2ETests.cs index b3c21d6..2938281 100644 --- a/Source/CdrAuthServer.E2ETests/US39327_CdrAuthServer_E2ETests.cs +++ b/Source/CdrAuthServer.E2ETests/US39327_CdrAuthServer_E2ETests.cs @@ -611,12 +611,12 @@ public static (string ExpectedHeading, string ExpectedDetail) GetExpectedCluster } } - public Task InitializeAsync() + public ValueTask InitializeAsync() { - return Task.CompletedTask; + return ValueTask.CompletedTask; } - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { if (_browserContext != null) { diff --git a/Source/CdrAuthServer.E2ETests/XUnit/Orderers/AlphabeticalOrderer.cs b/Source/CdrAuthServer.E2ETests/XUnit/Orderers/AlphabeticalOrderer.cs index e46cdba..2c79a1f 100644 --- a/Source/CdrAuthServer.E2ETests/XUnit/Orderers/AlphabeticalOrderer.cs +++ b/Source/CdrAuthServer.E2ETests/XUnit/Orderers/AlphabeticalOrderer.cs @@ -1,15 +1,27 @@ using System.Collections.Generic; using System.Linq; -using Xunit.Abstractions; using Xunit.Sdk; +using Xunit.v3; namespace CdrAuthServer.E2ETests.XUnit.Orderers { public class AlphabeticalOrderer : ITestCaseOrderer { - public IEnumerable OrderTestCases(IEnumerable testCases) - where TTestCase : ITestCase - => - testCases.OrderBy(testCase => testCase.TestMethod.Method.Name); + IReadOnlyCollection ITestCaseOrderer.OrderTestCases( + IReadOnlyCollection testCases) + { + return testCases.OrderBy(tc => ExtractTestName(tc)).ToList().AsReadOnly(); + } + + private static string ExtractTestName(ITestCase testCase) + { + var testMethod = testCase?.TestMethod; + if (testMethod is ITestMethodMetadata testMethodMetadata) + { + return testMethodMetadata.MethodName ?? string.Empty; + } + + return string.Empty; + } } } diff --git a/Source/CdrAuthServer.E2ETests/appsettings.Development.json b/Source/CdrAuthServer.E2ETests/appsettings.Development.json index 3f94233..b0a6374 100644 --- a/Source/CdrAuthServer.E2ETests/appsettings.Development.json +++ b/Source/CdrAuthServer.E2ETests/appsettings.Development.json @@ -1,6 +1,6 @@ { "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.XUnit", "Serilog.Sinks.Async" ], + "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Async" ], "MinimumLevel": { "Default": "Debug" }, diff --git a/Source/CdrAuthServer.E2ETests/appsettings.Release.json b/Source/CdrAuthServer.E2ETests/appsettings.Release.json index ec6ea65..fcbdd7d 100644 --- a/Source/CdrAuthServer.E2ETests/appsettings.Release.json +++ b/Source/CdrAuthServer.E2ETests/appsettings.Release.json @@ -1,6 +1,6 @@ { "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.XUnit", "Serilog.Sinks.Async" ], + "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Async" ], "MinimumLevel": { "Default": "Information" }, diff --git a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/BaseTest.cs b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/BaseTest.cs index b22ebd6..7e6b69f 100644 --- a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/BaseTest.cs +++ b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/BaseTest.cs @@ -6,6 +6,7 @@ using System.Configuration; using System.IO; using CdrAuthServer.GetDataRecipients.IntegrationTests.Fixtures; +using CdrAuthServer.GetDataRecipients.IntegrationTests.XUnit.Orderers; using Microsoft.Extensions.Configuration; using Xunit; @@ -13,7 +14,7 @@ namespace CdrAuthServer.GetDataRecipients.IntegrationTests { // Put all tests in same collection because we need them to run sequentially since some tests are mutating DB. [Collection("IntegrationTests")] - [TestCaseOrderer("CdrAuthServer.GetDataRecipients.IntegrationTests.XUnit.Orderers.AlphabeticalOrderer", "CdrAuthServer.GetDataRecipients.IntegrationTests")] + [TestCaseOrderer(typeof(AlphabeticalOrderer))] [DisplayTestMethodName] public abstract class BaseTest : IClassFixture { diff --git a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/CdrAuthServer.GetDataRecipients.IntegrationTests.csproj b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/CdrAuthServer.GetDataRecipients.IntegrationTests.csproj index 5351b2c..eb704fb 100644 --- a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/CdrAuthServer.GetDataRecipients.IntegrationTests.csproj +++ b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/CdrAuthServer.GetDataRecipients.IntegrationTests.csproj @@ -1,6 +1,7 @@  $(TargetFrameworkVersion) + Exe $(Version) $(Version) $(Version) @@ -22,9 +23,11 @@ + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -33,7 +36,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/DisplayTestMethodNameAttribute.cs b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/DisplayTestMethodNameAttribute.cs index 572f76b..9820ac5 100644 --- a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/DisplayTestMethodNameAttribute.cs +++ b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/DisplayTestMethodNameAttribute.cs @@ -8,8 +8,7 @@ using System.Reflection; using CdrAuthServer.GetDataRecipients.IntegrationTests.Fixtures; using Microsoft.Extensions.Configuration; -using Xunit; -using Xunit.Sdk; +using Xunit.v3; namespace CdrAuthServer.GetDataRecipients.IntegrationTests { @@ -17,12 +16,12 @@ internal class DisplayTestMethodNameAttribute : BeforeAfterTestAttribute { private static int count = 0; - public override void Before(MethodInfo methodUnderTest) + public override void Before(MethodInfo methodUnderTest, IXunitTest test) { Console.WriteLine($"Test #{++count} - {methodUnderTest.DeclaringType?.Name}.{methodUnderTest.Name}"); } - public override void After(MethodInfo methodUnderTest) + public override void After(MethodInfo methodUnderTest, IXunitTest test) { } } diff --git a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/Fixtures/TestFixture.cs b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/Fixtures/TestFixture.cs index 2112313..0216a7d 100644 --- a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/Fixtures/TestFixture.cs +++ b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/Fixtures/TestFixture.cs @@ -1,18 +1,18 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Xunit; namespace CdrAuthServer.GetDataRecipients.IntegrationTests.Fixtures { public class TestFixture : IAsyncLifetime { - public Task InitializeAsync() + public ValueTask InitializeAsync() { - return Task.CompletedTask; + return ValueTask.CompletedTask; } - public Task DisposeAsync() + public ValueTask DisposeAsync() { - return Task.CompletedTask; + return ValueTask.CompletedTask; } } } diff --git a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/XUnit/AlphabeticalOrderer.cs b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/XUnit/AlphabeticalOrderer.cs index ff15fce..d8f1173 100644 --- a/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/XUnit/AlphabeticalOrderer.cs +++ b/Source/CdrAuthServer.GetDataRecipients.IntegrationTests/XUnit/AlphabeticalOrderer.cs @@ -1,15 +1,27 @@ using System.Collections.Generic; using System.Linq; -using Xunit.Abstractions; using Xunit.Sdk; +using Xunit.v3; namespace CdrAuthServer.GetDataRecipients.IntegrationTests.XUnit.Orderers { public class AlphabeticalOrderer : ITestCaseOrderer { - public IEnumerable OrderTestCases(IEnumerable testCases) - where TTestCase : ITestCase - => - testCases.OrderBy(testCase => testCase.TestMethod.Method.Name); + IReadOnlyCollection ITestCaseOrderer.OrderTestCases( + IReadOnlyCollection testCases) + { + return testCases.OrderBy(tc => ExtractTestName(tc)).ToList().AsReadOnly(); + } + + private static string ExtractTestName(ITestCase testCase) + { + var testMethod = testCase?.TestMethod; + if (testMethod is ITestMethodMetadata testMethodMetadata) + { + return testMethodMetadata.MethodName ?? string.Empty; + } + + return string.Empty; + } } } diff --git a/Source/CdrAuthServer.GetDataRecipients/GetDataRecipientsFunction.cs b/Source/CdrAuthServer.GetDataRecipients/GetDataRecipientsFunction.cs index 4b5da93..3e78cc7 100644 --- a/Source/CdrAuthServer.GetDataRecipients/GetDataRecipientsFunction.cs +++ b/Source/CdrAuthServer.GetDataRecipients/GetDataRecipientsFunction.cs @@ -93,7 +93,7 @@ private static X509Certificate2 LoadCertificates(ILogger log, string cert, strin { log.LogInformation("Loading the certificate..."); byte[] certBytes = Convert.FromBase64String(cert); - X509Certificate2 certificate = new(certBytes, certPwd, X509KeyStorageFlags.MachineKeySet); + X509Certificate2 certificate = X509CertificateLoader.LoadPkcs12(certBytes, certPwd, X509KeyStorageFlags.MachineKeySet); return certificate; } diff --git a/Source/CdrAuthServer.Infrastructure/CdrAuthServer.Infrastructure.csproj b/Source/CdrAuthServer.Infrastructure/CdrAuthServer.Infrastructure.csproj index fbaa85e..85fbfe1 100644 --- a/Source/CdrAuthServer.Infrastructure/CdrAuthServer.Infrastructure.csproj +++ b/Source/CdrAuthServer.Infrastructure/CdrAuthServer.Infrastructure.csproj @@ -9,7 +9,7 @@ True - + all diff --git a/Source/CdrAuthServer.Infrastructure/Certificates/CertificateLoader.cs b/Source/CdrAuthServer.Infrastructure/Certificates/CertificateLoader.cs index 0c650e9..fec220f 100644 --- a/Source/CdrAuthServer.Infrastructure/Certificates/CertificateLoader.cs +++ b/Source/CdrAuthServer.Infrastructure/Certificates/CertificateLoader.cs @@ -38,10 +38,10 @@ private static X509Certificate2 LoadCertificateFromBytes(byte[] certBytes, strin { if (string.IsNullOrEmpty(password)) { - return new X509Certificate2(certBytes); + return X509CertificateLoader.LoadCertificate(certBytes); } - return new X509Certificate2(certBytes, password, X509KeyStorageFlags.Exportable); + return X509CertificateLoader.LoadPkcs12(certBytes, password, X509KeyStorageFlags.Exportable); } private static async Task DownloadData(string url) diff --git a/Source/CdrAuthServer.Infrastructure/Configuration/ConfigureSwaggerOptions.cs b/Source/CdrAuthServer.Infrastructure/Configuration/ConfigureSwaggerOptions.cs index 230664b..a667cbf 100644 --- a/Source/CdrAuthServer.Infrastructure/Configuration/ConfigureSwaggerOptions.cs +++ b/Source/CdrAuthServer.Infrastructure/Configuration/ConfigureSwaggerOptions.cs @@ -1,5 +1,5 @@ -using CdrAuthServer.Infrastructure.Models; -using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Asp.Versioning.ApiExplorer; +using CdrAuthServer.Infrastructure.Models; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Swashbuckle.AspNetCore.SwaggerGen; diff --git a/Source/CdrAuthServer.Infrastructure/Extensions/CdrSwaggerMiddlewareExtensions.cs b/Source/CdrAuthServer.Infrastructure/Extensions/CdrSwaggerMiddlewareExtensions.cs index 031c5f4..3ff1e08 100644 --- a/Source/CdrAuthServer.Infrastructure/Extensions/CdrSwaggerMiddlewareExtensions.cs +++ b/Source/CdrAuthServer.Infrastructure/Extensions/CdrSwaggerMiddlewareExtensions.cs @@ -1,5 +1,5 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Asp.Versioning.ApiExplorer; +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; namespace CdrAuthServer.Infrastructure.Extensions diff --git a/Source/CdrAuthServer.Infrastructure/Extensions/HttpExtensions.cs b/Source/CdrAuthServer.Infrastructure/Extensions/HttpExtensions.cs index 4b2f6a4..3996b50 100644 --- a/Source/CdrAuthServer.Infrastructure/Extensions/HttpExtensions.cs +++ b/Source/CdrAuthServer.Infrastructure/Extensions/HttpExtensions.cs @@ -8,7 +8,7 @@ public static class HttpExtensions { public static void SetClientCertificate(this HttpClientHandler clientHandler, string certificateFileName, string certificatePassword) { - clientHandler.ClientCertificates.Add(new X509Certificate2(certificateFileName, certificatePassword, X509KeyStorageFlags.Exportable)); + clientHandler.ClientCertificates.Add(X509CertificateLoader.LoadPkcs12FromFile(certificateFileName, certificatePassword, X509KeyStorageFlags.Exportable)); } public static bool IsSuccessful(this HttpStatusCode statusCode) diff --git a/Source/CdrAuthServer.Infrastructure/Models/CdrApiOptions.cs b/Source/CdrAuthServer.Infrastructure/Models/CdrApiOptions.cs index e24bc59..269f03f 100644 --- a/Source/CdrAuthServer.Infrastructure/Models/CdrApiOptions.cs +++ b/Source/CdrAuthServer.Infrastructure/Models/CdrApiOptions.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Http; +using System.Text.RegularExpressions; +using Microsoft.AspNetCore.Http; namespace CdrAuthServer.Infrastructure.Models { @@ -20,7 +21,7 @@ public class CdrApiOptions { foreach (var supportedApi in EndpointVersionOptions.OrderByDescending(v => v.Path.Length)) { - var regEx = new System.Text.RegularExpressions.Regex(supportedApi.Path); + var regEx = new Regex(supportedApi.Path, RegexOptions.None, TimeSpan.FromSeconds(2)); if (regEx.IsMatch(path)) { return supportedApi; diff --git a/Source/CdrAuthServer.Infrastructure/PrivateKeyJwt.cs b/Source/CdrAuthServer.Infrastructure/PrivateKeyJwt.cs index 82308c9..9485a92 100644 --- a/Source/CdrAuthServer.Infrastructure/PrivateKeyJwt.cs +++ b/Source/CdrAuthServer.Infrastructure/PrivateKeyJwt.cs @@ -21,7 +21,7 @@ public class PrivateKeyJwt /// The path to the certificate. /// The password of the certificate. public PrivateKeyJwt(string certFilePath, string pwd) - : this(new X509Certificate2(certFilePath, pwd, X509KeyStorageFlags.Exportable)) + : this(X509CertificateLoader.LoadPkcs12FromFile(certFilePath, pwd, X509KeyStorageFlags.Exportable)) { } diff --git a/Source/CdrAuthServer.Infrastructure/Versioning/ApiVersionErrorResponse.cs b/Source/CdrAuthServer.Infrastructure/Versioning/ApiVersionErrorResponse.cs deleted file mode 100644 index ab5bcbe..0000000 --- a/Source/CdrAuthServer.Infrastructure/Versioning/ApiVersionErrorResponse.cs +++ /dev/null @@ -1,50 +0,0 @@ -using CdrAuthServer.Domain.Models; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Versioning; -using Microsoft.Extensions.Logging; - -namespace CdrAuthServer.Infrastructure.Versioning -{ - public class ApiVersionErrorResponse : DefaultErrorResponseProvider - { - private readonly ILogger _logger; - - public ApiVersionErrorResponse() - { - _logger = new LoggerFactory().CreateLogger(); - } - - public override IActionResult CreateResponse(ErrorResponseContext context) - { - var errorList = new ResponseErrorList(); - int statusCode; - - // Determine what the return status code and message will be, default to 500 - Internal Server Error - if (context.Message.Contains(Domain.Constants.ErrorTitles.MissingVersion)) - { - errorList.AddInvalidXVMissingRequiredHeader(); - statusCode = StatusCodes.Status400BadRequest; - } - else if (context.Message.Contains(Domain.Constants.ErrorTitles.InvalidVersion)) - { - errorList.AddInvalidXVInvalidVersion(); - statusCode = StatusCodes.Status400BadRequest; - } - else if (context.Message.Contains(Domain.Constants.ErrorTitles.UnsupportedVersion)) - { - errorList.AddInvalidXVUnsupportedVersion(); - statusCode = StatusCodes.Status406NotAcceptable; - } - else - { - errorList.AddUnexpectedError(); - statusCode = StatusCodes.Status500InternalServerError; - } - - _logger.LogError("{Detail}", errorList.Errors[0].Detail); - - return new ObjectResult(errorList) { StatusCode = statusCode }; - } - } -} diff --git a/Source/CdrAuthServer.Infrastructure/Versioning/CdrVersionReader.cs b/Source/CdrAuthServer.Infrastructure/Versioning/CdrVersionReader.cs index 4396aa5..b8a6e35 100644 --- a/Source/CdrAuthServer.Infrastructure/Versioning/CdrVersionReader.cs +++ b/Source/CdrAuthServer.Infrastructure/Versioning/CdrVersionReader.cs @@ -1,6 +1,6 @@ -using CdrAuthServer.Infrastructure.Models; +using Asp.Versioning; +using CdrAuthServer.Infrastructure.Models; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Versioning; using Microsoft.Extensions.Primitives; namespace CdrAuthServer.Infrastructure.Versioning @@ -23,7 +23,7 @@ public void AddParameters(IApiVersionParameterDescriptionContext context) context.AddParameter("x-min-v", ApiVersionParameterLocation.Header); } - public string? Read(HttpRequest request) + public IReadOnlyList Read(HttpRequest request) { var endpointOption = _options.GetApiEndpointVersionOption(request.Path); @@ -35,18 +35,18 @@ public void AddParameters(IApiVersionParameterDescriptionContext context) else if (!endpointOption.IsVersioned) { #pragma warning disable S1135 // Track uses of "TODO" tags - return _options.DefaultVersion; // TODO: Check if we want to return a version at all + return new[] { _options.DefaultVersion }; // TODO: Check if we want to return a version at all #pragma warning restore S1135 // Track uses of "TODO" tags } // If x-min-v is passed in, we expect it to be a Positive Integer, the x-v value is parsed out of the header and will be validated by the Package itself // Refer to Standards here - https://consumerdatastandardsaustralia.github.io/standards/#http-headers - // When there is error in x-min-v, we return custom String x-min-v '' this is then manipulated in ApiVersionErrorResponse for a user friendly error message. + // When there is error in x-min-v, we return custom String x-min-v '' this is then manipulated by the caller for a user friendly error message. if (!request.Headers.TryGetValue("x-v", out var xvValue) || string.IsNullOrWhiteSpace(xvValue)) { if (endpointOption.IsXVHeaderMandatory) { - return Domain.Constants.ErrorTitles.MissingVersion; + return new[] { Domain.Constants.ErrorTitles.MissingVersion }; } xvValue = endpointOption.CurrentMinVersion.ToString(); @@ -60,12 +60,12 @@ public void AddParameters(IApiVersionParameterDescriptionContext context) var xvMinString = xvMinValue.FirstOrDefault() ?? string.Empty; - xvValue = CalculateVersion(xvInt, xvMinString, endpointOption); + var calculatedVersion = CalculateVersion(xvInt, xvMinString, endpointOption); - return xvValue; + return new[] { calculatedVersion ?? string.Empty }; } - return Domain.Constants.ErrorTitles.InvalidVersion; + return new[] { Domain.Constants.ErrorTitles.InvalidVersion }; } private static string? CalculateVersion(int xvInt, string xvMinString, CdrApiEndpointVersionOptions endpointOption) diff --git a/Source/CdrAuthServer.IntegrationTests/BaseTest.cs b/Source/CdrAuthServer.IntegrationTests/BaseTest.cs index 369f4aa..4ec654d 100644 --- a/Source/CdrAuthServer.IntegrationTests/BaseTest.cs +++ b/Source/CdrAuthServer.IntegrationTests/BaseTest.cs @@ -1,4 +1,5 @@ -using ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation; +using CdrAuthServer.IntegrationTests.XUnit.Orderers; +using ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation; using Microsoft.Extensions.Configuration; using Xunit; using Xunit.DependencyInjection; @@ -7,11 +8,11 @@ namespace CdrAuthServer.IntegrationTests { // Put all tests in same collection because we need them to run sequentially since some tests are mutating DB. [Collection("IntegrationTests")] - [TestCaseOrderer("CdrAuthServer.IntegrationTests.XUnit.Orderers.AlphabeticalOrderer", "CdrAuthServer.IntegrationTests")] + [TestCaseOrderer(typeof(AlphabeticalOrderer))] public abstract class BaseTest : SharedBaseTest { protected BaseTest(ITestOutputHelperAccessor testOutputHelperAccessor, IConfiguration config) - : base(testOutputHelperAccessor, config) + : base(config) { } } diff --git a/Source/CdrAuthServer.IntegrationTests/CdrAuthServer.IntegrationTests.csproj b/Source/CdrAuthServer.IntegrationTests/CdrAuthServer.IntegrationTests.csproj index da9572a..0eade4a 100644 --- a/Source/CdrAuthServer.IntegrationTests/CdrAuthServer.IntegrationTests.csproj +++ b/Source/CdrAuthServer.IntegrationTests/CdrAuthServer.IntegrationTests.csproj @@ -1,6 +1,7 @@  $(TargetFrameworkVersion) + Exe $(Version) $(Version) $(Version) @@ -8,7 +9,6 @@ Debug;Release;Shared enable enable - true True @@ -36,6 +36,8 @@ + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_Authorise.cs b/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_Authorise.cs index 54e7e06..0d7cd49 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_Authorise.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_Authorise.cs @@ -64,7 +64,7 @@ public async Task AC01_MDH_JARM_AC01_HappyPath_JARM_Response_Mode_jwt() responseType: responseType, state: STATE); - var parResponseMessageContent = await parResponseMessage.Content.ReadAsStringAsync(); + var parResponseMessageContent = await parResponseMessage.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); parResponseMessage.StatusCode.Should().Be(HttpStatusCode.Created, because: parResponseMessageContent); var parResponse = JsonConvert.DeserializeObject(parResponseMessageContent); @@ -101,7 +101,7 @@ public async Task AC01_MDH_JARM_AC01_HappyPath_JARM_Response_Mode_jwt() encryptedJwt.Header["enc"].Should().Be("A128CBC-HS256", because: "JARM Encryption is turned on."); // Decrypt the JARM JWT. - var privateKeyCertificate = new X509Certificate2(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); + var privateKeyCertificate = X509CertificateLoader.LoadPkcs12FromFile(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); var privateKey = privateKeyCertificate.GetRSAPrivateKey(); JweToken token = JWE.Decrypt(queryValueResponse, privateKey); encodedJwt = token.Plaintext; diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_DCR.cs b/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_DCR.cs index fa0a0a4..75e003f 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_DCR.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_DCR.cs @@ -174,7 +174,7 @@ public async Task AC06_MDHJWKS_AC2_POST_With_SoftwareIDAlreadyRegistered_ShouldR // Check it was registered if (responseMessageSetup.StatusCode != HttpStatusCode.Created) { - throw new Exception($"expected Created - {await responseMessageSetup.Content.ReadAsStringAsync()}"); + throw new Exception($"expected Created - {await responseMessageSetup.Content.ReadAsStringAsync(TestContext.Current.CancellationToken)}"); } // Act - Now try and register it again diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_PAR.cs b/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_PAR.cs index 2c9e6fc..17e8eac 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_PAR.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/JARM/US44264_CdrAuthServer_JARM_PAR.cs @@ -92,7 +92,7 @@ public async Task AC01_MDHPAR_AC01_HappyPath_ShouldRespondWith_201Created(Respon responseType: responseType, responseMode: responseMode); - var responseText = await response.Content.ReadAsStringAsync(); + var responseText = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/US12678_CdrAuthServer_Authorisation.cs b/Source/CdrAuthServer.IntegrationTests/Tests/US12678_CdrAuthServer_Authorisation.cs index 3921e9f..bae0e42 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/US12678_CdrAuthServer_Authorisation.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/US12678_CdrAuthServer_Authorisation.cs @@ -19,7 +19,6 @@ using Microsoft.Extensions.Options; using Serilog; using Xunit; -using XUnit_Skippable; using Xunit.DependencyInjection; using static ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation.Services.DataHolderAuthoriseService; using Constants = ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation.Constants; @@ -155,7 +154,7 @@ public async Task AC02_InactiveOrRemovedSoftwareProduct_ShouldReturn_AdrStatusNo var request = new HttpRequestMessage(HttpMethod.Get, authorisationURL); - var authResponse = await Helpers.Web.CreateHttpClient(allowAutoRedirect: false).SendAsync(request); + var authResponse = await Helpers.Web.CreateHttpClient(allowAutoRedirect: false).SendAsync(request, TestContext.Current.CancellationToken); // Check query has "response" param var queryValues = HttpUtility.ParseQueryString(authResponse?.Headers.Location?.Query ?? throw new NullReferenceException()); @@ -166,7 +165,7 @@ public async Task AC02_InactiveOrRemovedSoftwareProduct_ShouldReturn_AdrStatusNo if (_authServerOptions.JARM_ENCRYPTION_ON) { // Decrypt the JARM JWT. - var privateKeyCertificate = new X509Certificate2( + var privateKeyCertificate = X509CertificateLoader.LoadPkcs12FromFile( Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); var privateKey = privateKeyCertificate.GetRSAPrivateKey(); @@ -185,7 +184,7 @@ public async Task AC02_InactiveOrRemovedSoftwareProduct_ShouldReturn_AdrStatusNo } } - [SkippableTheory] + [Theory] [InlineData("code id_token", HttpStatusCode.Redirect, true)] [InlineData("foo", HttpStatusCode.Redirect, false)] // Unsuccessful request should redirect back to DR public async Task AC02_Get_WithInvalidResponseType_ShouldRespondWith_302Redirect_ErrorResponse(string responseType, HttpStatusCode expectedStatusCode, bool useSpecificRedirectUrl) @@ -194,7 +193,7 @@ public async Task AC02_Get_WithInvalidResponseType_ShouldRespondWith_302Redirect if (_authServerOptions.HEADLESSMODE) { - throw new SkipTestException("Test not applicable for headless mode."); + Assert.Skip("Test not applicable for headless mode."); } string? expectedRedirectFragment = null; @@ -221,7 +220,7 @@ public async Task AC02_Get_WithInvalidResponseType_ShouldRespondWith_302Redirect Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); - var response = await CreateHttpClient().SendAsync(request); + var response = await CreateHttpClient().SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) @@ -242,7 +241,7 @@ public async Task AC02_Get_WithInvalidResponseType_ShouldRespondWith_302Redirect } } - [SkippableTheory] + [Theory] [InlineData(null, HttpStatusCode.Redirect, true)] [InlineData("foo", HttpStatusCode.BadRequest)] public async Task AC03_Get_WithInvalidRequestBody_ShouldRespondWith_400BadRequest_ErrorResponse(string requestBody, HttpStatusCode expectedStatusCode, bool useSpecificUrl = false) @@ -251,7 +250,7 @@ public async Task AC03_Get_WithInvalidRequestBody_ShouldRespondWith_400BadReques if (_authServerOptions.HEADLESSMODE) { - throw new SkipTestException("Test not applicable for headless mode."); + Assert.Skip("Test not applicable for headless mode."); } var expectedRedirectPath = string.Empty; @@ -271,7 +270,7 @@ public async Task AC03_Get_WithInvalidRequestBody_ShouldRespondWith_400BadReques Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); - var response = await CreateHttpClient().SendAsync(request); + var response = await CreateHttpClient().SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) @@ -289,7 +288,7 @@ public async Task AC03_Get_WithInvalidRequestBody_ShouldRespondWith_400BadReques } } - [SkippableTheory] + [Theory] [InlineData(false, HttpStatusCode.Redirect)] // Successful request should redirect to the DH login URI [InlineData( true, // Additional unsupported scope should be ignored @@ -300,7 +299,7 @@ public async Task AC04_Get_WithInvalidScope_ShouldRespondWith_200OK_Response(boo if (_authServerOptions.HEADLESSMODE) { - throw new SkipTestException("Test not applicable for headless mode."); + Assert.Skip("Test not applicable for headless mode."); } var expectedRedirectPath = _accountLoginUrl; @@ -323,7 +322,7 @@ public async Task AC04_Get_WithInvalidScope_ShouldRespondWith_200OK_Response(boo Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); // Act - var response = await CreateHttpClient().SendAsync(request); + var response = await CreateHttpClient().SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) @@ -337,7 +336,7 @@ public async Task AC04_Get_WithInvalidScope_ShouldRespondWith_200OK_Response(boo } } - [SkippableTheory] + [Theory] [InlineData(Constants.Scopes.ScopeBanking, HttpStatusCode.Redirect, false)] [InlineData(Constants.Scopes.ScopeBankingWithoutOpenId, HttpStatusCode.Redirect, true)] public async Task AC05_Get_WithScopeMissingOpenId_ShouldRespondWith_302Redirect_ErrorResponse( @@ -349,7 +348,7 @@ public async Task AC05_Get_WithScopeMissingOpenId_ShouldRespondWith_302Redirect_ if (_authServerOptions.HEADLESSMODE) { - throw new SkipTestException("Test not applicable for headless mode."); + Assert.Skip("Test not applicable for headless mode."); } var expectedError = new MissingOpenIdScopeException(); @@ -378,7 +377,7 @@ public async Task AC05_Get_WithScopeMissingOpenId_ShouldRespondWith_302Redirect_ Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); - var response = await CreateHttpClient().SendAsync(request); + var response = await CreateHttpClient().SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) @@ -399,14 +398,14 @@ public async Task AC05_Get_WithScopeMissingOpenId_ShouldRespondWith_302Redirect_ } } - [SkippableTheory] + [Theory] [InlineData(Constants.SoftwareProducts.SoftwareProductId, HttpStatusCode.Redirect, true)] [InlineData(Constants.GuidFoo, HttpStatusCode.Redirect, false)] // Unsuccessful request should redirect back to DR public async Task AC06_Get_WithInvalidClientID_ShouldRespondWith_302Redirect_ErrorResponse(string softwareProductId, HttpStatusCode expectedStatusCode, bool useSpecificUrl) { if (_authServerOptions.HEADLESSMODE) { - throw new SkipTestException("Test not applicable for headless mode."); + Assert.Skip("Test not applicable for headless mode."); } string? expectedRedirectFragment = null; @@ -436,7 +435,7 @@ public async Task AC06_Get_WithInvalidClientID_ShouldRespondWith_302Redirect_Err Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); - var response = await CreateHttpClient().SendAsync(request); + var response = await CreateHttpClient().SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) @@ -457,12 +456,12 @@ public async Task AC06_Get_WithInvalidClientID_ShouldRespondWith_302Redirect_Err } } - [SkippableFact] + [Fact] public async Task AC07_Get_WithValidRedirectURI_Success() { if (_authServerOptions.HEADLESSMODE) { - throw new SkipTestException("Test not applicable for headless mode."); + Assert.Skip("Test not applicable for headless mode."); } var expectedRedirectPath = _options.SOFTWAREPRODUCT_REDIRECT_URI_FOR_INTEGRATION_TESTS; @@ -478,7 +477,7 @@ public async Task AC07_Get_WithValidRedirectURI_Success() Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); - var response = await CreateHttpClient().SendAsync(request); + var response = await CreateHttpClient().SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) @@ -488,12 +487,12 @@ public async Task AC07_Get_WithValidRedirectURI_Success() } } - [SkippableFact] + [Fact] public async Task AC07_Get_WithInvalidRedirectURI_ShouldRespondWith_400BadRequest_ErrorResponse() { if (_authServerOptions.HEADLESSMODE) { - throw new SkipTestException("Test not applicable for headless mode."); + Assert.Skip("Test not applicable for headless mode."); } var expectedError = new InvalidRequestException(string.Empty); // TODO: Why doesn't this use a description? Bug 64158 @@ -510,7 +509,7 @@ public async Task AC07_Get_WithInvalidRedirectURI_ShouldRespondWith_400BadReques Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); - var response = await CreateHttpClient().SendAsync(request); + var response = await CreateHttpClient().SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) @@ -519,7 +518,7 @@ public async Task AC07_Get_WithInvalidRedirectURI_ShouldRespondWith_400BadReques } } - [SkippableTheory] + [Theory] [InlineData(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, HttpStatusCode.Redirect, true)] [InlineData(Constants.Certificates.InvalidCertificateFilename, Constants.Certificates.InvalidCertificatePassword, HttpStatusCode.Redirect, false)] // Unsuccessful request should redirect back to DR public async Task AC08_Get_WithUnsignedRequestBody_ShouldRespondWith_302Redirect_ErrorResponse( @@ -530,7 +529,7 @@ public async Task AC08_Get_WithUnsignedRequestBody_ShouldRespondWith_302Redirect { if (_authServerOptions.HEADLESSMODE) { - throw new SkipTestException("Test not applicable for headless mode."); + Assert.Skip("Test not applicable for headless mode."); } var expectedError = new InvalidJwtException(); @@ -556,7 +555,7 @@ public async Task AC08_Get_WithUnsignedRequestBody_ShouldRespondWith_302Redirect Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); - var response = await CreateHttpClient().SendAsync(request); + var response = await CreateHttpClient().SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/US12962_CdrAuthServer_OIDC_Configuration.cs b/Source/CdrAuthServer.IntegrationTests/Tests/US12962_CdrAuthServer_OIDC_Configuration.cs index 10e9a4a..2ed4eb5 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/US12962_CdrAuthServer_OIDC_Configuration.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/US12962_CdrAuthServer_OIDC_Configuration.cs @@ -48,7 +48,7 @@ public async Task AC01_FromMDH_Get_ShouldRespondWith_200OK_OIDC_Configuration() Assertions.AssertHasContentTypeApplicationJson(response.Content); // Assert - Check json - var actualJson = await response.Content.ReadAsStringAsync(); + var actualJson = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var actual = JsonConvert.DeserializeObject(actualJson); actual.issuer.Should().Be(_authServerOptions.CDRAUTHSERVER_BASEURI); diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/US12963_CdrAuthServer_Token.cs b/Source/CdrAuthServer.IntegrationTests/Tests/US12963_CdrAuthServer_Token.cs index 38ac0ad..c309077 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/US12963_CdrAuthServer_Token.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/US12963_CdrAuthServer_Token.cs @@ -98,7 +98,7 @@ private static void AssertIdToken(string? idToken) if (!string.IsNullOrEmpty(handler.ReadJwtToken(idToken).Header.Enc)) { // Decrypt the id token. - var privateKeyCertificate = new X509Certificate2(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); + var privateKeyCertificate = X509CertificateLoader.LoadPkcs12FromFile(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); var privateKey = privateKeyCertificate.GetRSAPrivateKey(); JweToken token = JWE.Decrypt(idToken, privateKey); decryptedIdToken = token.Plaintext; @@ -826,7 +826,7 @@ public async Task ACX03_UseExpiredRefreshToken_ShouldRespondWith_400BadRequest(b _ = new JwtSecurityTokenHandler().ReadJwtToken(tokenResponse?.AccessToken); // Arrange - wait until refresh token has expired - await Task.Delay((SHARING_DURATION_FOR_EXPIRED_REFRESHTOKEN + 10) * 1000); + await Task.Delay((SHARING_DURATION_FOR_EXPIRED_REFRESHTOKEN + 10) * 1000, TestContext.Current.CancellationToken); } // Act - Use refresh token to get access token and refresh token @@ -899,7 +899,7 @@ private string GenerateClientAssertion(AC04_TestType testType) expires = now.AddMinutes(10); } - var certificate = new X509Certificate2(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); + var certificate = X509CertificateLoader.LoadPkcs12FromFile(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); var x509SigningCredentials = new X509SigningCredentials(certificate, SecurityAlgorithms.RsaSsaPssSha256); var jwt = new JwtSecurityToken( diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/US12964_CDRAuthServer_OIDC_JWKS.cs b/Source/CdrAuthServer.IntegrationTests/Tests/US12964_CDRAuthServer_OIDC_JWKS.cs index 0a62c95..76515f7 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/US12964_CDRAuthServer_OIDC_JWKS.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/US12964_CDRAuthServer_OIDC_JWKS.cs @@ -62,7 +62,7 @@ public async Task AC01_FromMDH_Get_ShouldRespondWith_200OK_OIDC_JWKS() Assertions.AssertHasContentTypeApplicationJson(response.Content); // Assert - Check JWKS - var actualJson = await response.Content.ReadAsStringAsync(); + var actualJson = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var actual = JsonConvert.DeserializeObject(actualJson); actual.Keys.Should().NotBeNull(); actual.Keys?.Length.Should().Be(2); diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/US12966_CdrAuthServer_Introspection.cs b/Source/CdrAuthServer.IntegrationTests/Tests/US12966_CdrAuthServer_Introspection.cs index 28995fb..88aa7c0 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/US12966_CdrAuthServer_Introspection.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/US12966_CdrAuthServer_Introspection.cs @@ -90,7 +90,7 @@ public async Task AC01_Post_ShouldRespondWith_200OK_IntrospectionInfo(TokenType // Assert - Check status code response.StatusCode.Should().Be(HttpStatusCode.OK); - var actualJson = await response.Content.ReadAsStringAsync(); + var actualJson = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var actual = JsonConvert.DeserializeObject(actualJson); actual.Should().NotBeNull(); @@ -129,7 +129,7 @@ public async Task AC02_Post_WithInvalidRefreshToken_ShouldRespondWith_200OK_Acti { response.StatusCode.Should().Be(HttpStatusCode.OK); - var actualJson = await response.Content.ReadAsStringAsync(); + var actualJson = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var actual = JsonConvert.DeserializeObject(actualJson); actual.Should().NotBeNull(); @@ -158,7 +158,7 @@ public async Task AC03_Post_WithMissingRefreshToken_ShouldRespondWith_200OK_Acti { response.StatusCode.Should().Be(HttpStatusCode.OK); - var actualJson = await response.Content.ReadAsStringAsync(); + var actualJson = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var actual = JsonConvert.DeserializeObject(actualJson); actual.Should().NotBeNull(); @@ -184,7 +184,7 @@ public async Task AC04_Post_WithExpiredRefreshToken_ShouldRespondWith_200OK_Acti tokenResponse = await _authorizationService.GetToken(TokenType.KamillaSmith, tokenLifetime: EXPIRED_LIFETIME_SECONDS, sharingDuration: EXPIRED_LIFETIME_SECONDS); // Wait for token to expire - await Task.Delay((EXPIRED_LIFETIME_SECONDS + 5) * 1000); + await Task.Delay((EXPIRED_LIFETIME_SECONDS + 5) * 1000, TestContext.Current.CancellationToken); } else { @@ -199,7 +199,7 @@ public async Task AC04_Post_WithExpiredRefreshToken_ShouldRespondWith_200OK_Acti { response.StatusCode.Should().Be(HttpStatusCode.OK); - var actualJson = await response.Content.ReadAsStringAsync(); + var actualJson = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var actual = JsonConvert.DeserializeObject(actualJson); actual.Should().NotBeNull(); diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/US12968_CdrAuthServer_PAR.cs b/Source/CdrAuthServer.IntegrationTests/Tests/US12968_CdrAuthServer_PAR.cs index f46c6fa..e1537ff 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/US12968_CdrAuthServer_PAR.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/US12968_CdrAuthServer_PAR.cs @@ -307,7 +307,7 @@ public async Task AC03_Post_AuthorisationEndpoint_WithRequestUri_After90Seconds_ } // Wait until PAR expires - await Task.Delay((PAR_EXPIRY_SECONDS + 10) * 1000); + await Task.Delay((PAR_EXPIRY_SECONDS + 10) * 1000, TestContext.Current.CancellationToken); // May need to provide a clientId here! var authorisationURL = new AuthoriseUrl.AuthoriseUrlBuilder(_options) @@ -322,7 +322,7 @@ public async Task AC03_Post_AuthorisationEndpoint_WithRequestUri_After90Seconds_ Helpers.AuthServer.AttachHeadersForStandAlone(request.RequestUri?.AbsoluteUri ?? throw new NullReferenceException(), request.Headers, _options.DH_MTLS_GATEWAY_URL, _authServerOptions.XTLSCLIENTCERTTHUMBPRINT, _authServerOptions.STANDALONE); - var authResponse = await Helpers.Web.CreateHttpClient(allowAutoRedirect: false).SendAsync(request); + var authResponse = await Helpers.Web.CreateHttpClient(allowAutoRedirect: false).SendAsync(request, TestContext.Current.CancellationToken); // Assert using (new AssertionScope(BaseTestAssertionStrategy)) @@ -345,7 +345,7 @@ public async Task AC03_Post_AuthorisationEndpoint_WithRequestUri_After90Seconds_ if (_authServerOptions.JARM_ENCRYPTION_ON) { // Decrypt the JARM JWT. - var privateKeyCertificate = new X509Certificate2(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); + var privateKeyCertificate = X509CertificateLoader.LoadPkcs12FromFile(Constants.Certificates.JwtCertificateFilename, Constants.Certificates.JwtCertificatePassword, X509KeyStorageFlags.Exportable); var privateKey = privateKeyCertificate.GetRSAPrivateKey(); JweToken token = JWE.Decrypt(queryValueResponse, privateKey); encodedJwt = token.Plaintext; diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/US15221_US12969_US15584_CdrAuthServer_Registration_POST.cs b/Source/CdrAuthServer.IntegrationTests/Tests/US15221_US12969_US15584_CdrAuthServer_Registration_POST.cs index 8040de8..f146fbb 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/US15221_US12969_US15584_CdrAuthServer_Registration_POST.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/US15221_US12969_US15584_CdrAuthServer_Registration_POST.cs @@ -76,7 +76,7 @@ public async Task AC01_Post_WithUnregistedSoftwareProduct_ShouldRespondWith_201C // Assert using (new AssertionScope(BaseTestAssertionStrategy)) { - var responseContent = await response.Content.ReadAsStringAsync(); + var responseContent = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); response.StatusCode.Should().Be( HttpStatusCode.Created, $"NB: response.Content is {responseContent}"); @@ -120,7 +120,7 @@ public async Task AC01_Post_WithUnregistedSoftwareProduct_MandatoryOnlyFields_Sh // Assert using (new AssertionScope(BaseTestAssertionStrategy)) { - var responseContent = await response.Content.ReadAsStringAsync(); + var responseContent = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); response.StatusCode.Should().Be( HttpStatusCode.Created, $"NB: response.Content is {responseContent}"); diff --git a/Source/CdrAuthServer.IntegrationTests/Tests/US18469_CdrAuthServer_TokenRevocation.cs b/Source/CdrAuthServer.IntegrationTests/Tests/US18469_CdrAuthServer_TokenRevocation.cs index b18125a..a8919ce 100644 --- a/Source/CdrAuthServer.IntegrationTests/Tests/US18469_CdrAuthServer_TokenRevocation.cs +++ b/Source/CdrAuthServer.IntegrationTests/Tests/US18469_CdrAuthServer_TokenRevocation.cs @@ -56,16 +56,16 @@ public US18469_CdrAuthServer_TokenRevocation( _apiServiceDirector = apiServiceDirector ?? throw new ArgumentNullException(nameof(apiServiceDirector)); } - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { // Purge Authorisation Server Registrations and create a clean registration for each test to ensure test independance. Helpers.AuthServer.PurgeAuthServerForDataholder(_options); await _dataHolderRegisterService.RegisterSoftwareProduct(responseType: ResponseType.Code); } - public Task DisposeAsync() + public ValueTask DisposeAsync() { - return Task.CompletedTask; + return ValueTask.CompletedTask; } // Call authorise/token endpoints to create access and refresh tokens diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Orderers/AlphabeticalOrderer.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Orderers/AlphabeticalOrderer.cs index 33ee195..1ee7d7c 100644 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Orderers/AlphabeticalOrderer.cs +++ b/Source/CdrAuthServer.IntegrationTests/XUnit/Orderers/AlphabeticalOrderer.cs @@ -1,13 +1,27 @@ -using Xunit.Abstractions; +using System.Collections.Generic; +using System.Linq; using Xunit.Sdk; +using Xunit.v3; namespace CdrAuthServer.IntegrationTests.XUnit.Orderers { public class AlphabeticalOrderer : ITestCaseOrderer { - public IEnumerable OrderTestCases(IEnumerable testCases) - where TTestCase : ITestCase - => - testCases.OrderBy(testCase => testCase.TestMethod.Method.Name); + IReadOnlyCollection ITestCaseOrderer.OrderTestCases( + IReadOnlyCollection testCases) + { + return testCases.OrderBy(tc => ExtractTestName(tc)).ToList().AsReadOnly(); + } + + private static string ExtractTestName(ITestCase testCase) + { + var testMethod = testCase?.TestMethod; + if (testMethod is ITestMethodMetadata testMethodMetadata) + { + return testMethodMetadata.MethodName ?? string.Empty; + } + + return string.Empty; + } } } diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/Samples.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/Samples.cs deleted file mode 100644 index 4e484f9..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/Samples.cs +++ /dev/null @@ -1,57 +0,0 @@ -#undef HIDE // MJS - don't want these samples running -#if HIDE -using Xunit; - -namespace XUnit_Skippable -{ - public class Samples - { - public class Facts - { - [Fact] - public void NonSkippableFact() { } - - [SkippableFact] - public void Passing() { } - - [SkippableFact(Skip = "I never feel like it")] - public void StaticallySkipped() { } - - [SkippableFact] - public void DynamicallySkipped() - { - // You could hide this behind something like "Assert.Skip", by bring in the assertion - // library as source and extending the Assert class. - throw new SkipTestException("I don't feel like it right now, ask again later"); - } - - [SkippableFact] - public void Failing() - { - Assert.True(false); - } - } - - public class Theories - { - [SkippableTheory(Skip = "I never feel like it")] -#pragma warning disable xUnit1003 // Since this theory is skipped, it doesn't need data -#pragma warning disable xUnit1006 // Since this theory is skipped, it doesn't need parameters - public void StaticallySkipped() { } -#pragma warning restore xUnit1006 -#pragma warning restore xUnit1003 - - [SkippableTheory] - [InlineData(null)] - [InlineData("Hello, world!")] - public void DynamicallySkipped(string value) - { - if (value == null) - throw new SkipTestException("I don't like to run against null data."); - - Assert.StartsWith("foo", value); - } - } - } -} -#endif diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkipTestException.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkipTestException.cs deleted file mode 100644 index be763f5..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkipTestException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace XUnit_Skippable -{ - public class SkipTestException : Exception - { - public SkipTestException(string reason) - : base(reason) - { - } - } -} diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkippableFactAttribute.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkippableFactAttribute.cs deleted file mode 100644 index 9b4bc98..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkippableFactAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Xunit; -using Xunit.Sdk; - -namespace XUnit_Skippable -{ - [XunitTestCaseDiscoverer("CdrAuthServer.IntegrationTests.XUnit_Skippable.SkippableFactDiscoverer", "CdrAuthServer.IntegrationTests")] - public class SkippableFactAttribute : FactAttribute - { - } -} diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkippableTheoryAttribute.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkippableTheoryAttribute.cs deleted file mode 100644 index 5fd862d..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/SkippableTheoryAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Xunit; -using Xunit.Sdk; - -namespace XUnit_Skippable -{ - [XunitTestCaseDiscoverer("CdrAuthServer.IntegrationTests.XUnit_Skippable.SkippableTheoryDiscoverer", "CdrAuthServer.IntegrationTests")] - public class SkippableTheoryAttribute : TheoryAttribute - { - } -} diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactDiscoverer.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactDiscoverer.cs deleted file mode 100644 index bd77492..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactDiscoverer.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace XUnit_Skippable -{ - public class SkippableFactDiscoverer : IXunitTestCaseDiscoverer - { - private readonly IMessageSink diagnosticMessageSink; - - public SkippableFactDiscoverer(IMessageSink diagnosticMessageSink) - { - this.diagnosticMessageSink = diagnosticMessageSink; - } - - public IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute) - { - yield return new SkippableFactTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), discoveryOptions.MethodDisplayOptionsOrDefault(), testMethod); - } - } -} diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactMessageBus.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactMessageBus.cs deleted file mode 100644 index bee38ff..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactMessageBus.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Linq; -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace XUnit_Skippable -{ - public class SkippableFactMessageBus : IMessageBus - { - private readonly IMessageBus innerBus; - - public SkippableFactMessageBus(IMessageBus innerBus) - { - this.innerBus = innerBus; - } - - public int DynamicallySkippedTestCount { get; private set; } - - public void Dispose() - { - } - - public bool QueueMessage(IMessageSinkMessage message) - { - var testFailed = message as ITestFailed; - if (testFailed != null) - { - var exceptionType = testFailed.ExceptionTypes.FirstOrDefault(); - if (exceptionType == typeof(SkipTestException).FullName) - { - DynamicallySkippedTestCount++; - return innerBus.QueueMessage(new TestSkipped(testFailed.Test, testFailed.Messages.FirstOrDefault())); - } - } - - // Nothing we care about, send it on its way - return innerBus.QueueMessage(message); - } - } -} diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactTestCase.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactTestCase.cs deleted file mode 100644 index a7fa533..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableFactTestCase.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.ComponentModel; -using Xunit.Abstractions; -using Xunit.Sdk; - -#nullable disable - -namespace XUnit_Skippable -{ - public class SkippableFactTestCase : XunitTestCase - { - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")] - public SkippableFactTestCase() - { - } - - public SkippableFactTestCase(IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, TestMethodDisplayOptions defaultMethodDisplayOptions, ITestMethod testMethod, object[] testMethodArguments = null) - : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod, testMethodArguments) - { - } - - public override async Task RunAsync( - IMessageSink diagnosticMessageSink, - IMessageBus messageBus, - object[] constructorArguments, - ExceptionAggregator aggregator, - CancellationTokenSource cancellationTokenSource) - { - var skipMessageBus = new SkippableFactMessageBus(messageBus); - var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, constructorArguments, aggregator, cancellationTokenSource); - if (skipMessageBus.DynamicallySkippedTestCount > 0) - { - result.Failed -= skipMessageBus.DynamicallySkippedTestCount; - result.Skipped += skipMessageBus.DynamicallySkippedTestCount; - } - - return result; - } - } -} diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableTheoryDiscoverer.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableTheoryDiscoverer.cs deleted file mode 100644 index 5e19471..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableTheoryDiscoverer.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace XUnit_Skippable -{ - public class SkippableTheoryDiscoverer : IXunitTestCaseDiscoverer - { - private readonly IMessageSink diagnosticMessageSink; - private readonly TheoryDiscoverer theoryDiscoverer; - - public SkippableTheoryDiscoverer(IMessageSink diagnosticMessageSink) - { - this.diagnosticMessageSink = diagnosticMessageSink; - - theoryDiscoverer = new TheoryDiscoverer(diagnosticMessageSink); - } - - public IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute) - { - var defaultMethodDisplay = discoveryOptions.MethodDisplayOrDefault(); - var defaultMethodDisplayOptions = discoveryOptions.MethodDisplayOptionsOrDefault(); - - // Unlike fact discovery, the underlying algorithm for theories is complex, so we let the theory discoverer - // do its work, and do a little on-the-fly conversion into our own test cases. - return theoryDiscoverer.Discover(discoveryOptions, testMethod, factAttribute) - .Select(testCase => testCase is XunitTheoryTestCase - ? (IXunitTestCase)new SkippableTheoryTestCase(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testCase.TestMethod) - : new SkippableFactTestCase(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testCase.TestMethod, testCase.TestMethodArguments)); - } - } -} diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableTheoryTestCase.cs b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableTheoryTestCase.cs deleted file mode 100644 index f26b716..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/XunitExtensions/SkippableTheoryTestCase.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.ComponentModel; -using System.Threading; -using System.Threading.Tasks; -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace XUnit_Skippable -{ - public class SkippableTheoryTestCase : XunitTheoryTestCase - { - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")] - public SkippableTheoryTestCase() - { - } - - public SkippableTheoryTestCase(IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, TestMethodDisplayOptions defaultMethodDisplayOptions, ITestMethod testMethod) - : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod) - { - } - - public override async Task RunAsync( - IMessageSink diagnosticMessageSink, - IMessageBus messageBus, - object[] constructorArguments, - ExceptionAggregator aggregator, - CancellationTokenSource cancellationTokenSource) - { - // Duplicated code from SkippableFactTestCase. I'm sure we could find a way to de-dup with some thought. - var skipMessageBus = new SkippableFactMessageBus(messageBus); - var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, constructorArguments, aggregator, cancellationTokenSource); - if (skipMessageBus.DynamicallySkippedTestCount > 0) - { - result.Failed -= skipMessageBus.DynamicallySkippedTestCount; - result.Skipped += skipMessageBus.DynamicallySkippedTestCount; - } - - return result; - } - } -} diff --git a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/readme.md b/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/readme.md deleted file mode 100644 index 51fd81f..0000000 --- a/Source/CdrAuthServer.IntegrationTests/XUnit/Skippable/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -Skippable tests at runtime. - -See https://github.com/xunit/samples.xunit/tree/main/DynamicSkipExample \ No newline at end of file diff --git a/Source/CdrAuthServer.IntegrationTests/appsettings.Development.json b/Source/CdrAuthServer.IntegrationTests/appsettings.Development.json index b06a6c8..04709ff 100644 --- a/Source/CdrAuthServer.IntegrationTests/appsettings.Development.json +++ b/Source/CdrAuthServer.IntegrationTests/appsettings.Development.json @@ -1,6 +1,6 @@ { "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.XUnit", "Serilog.Sinks.Async" ], + "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Async" ], "MinimumLevel": { "Default": "Debug" }, diff --git a/Source/CdrAuthServer.IntegrationTests/appsettings.Release.json b/Source/CdrAuthServer.IntegrationTests/appsettings.Release.json index 5555293..50925a3 100644 --- a/Source/CdrAuthServer.IntegrationTests/appsettings.Release.json +++ b/Source/CdrAuthServer.IntegrationTests/appsettings.Release.json @@ -1,6 +1,6 @@ { "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.XUnit", "Serilog.Sinks.Async" ], + "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Async" ], "MinimumLevel": { "Default": "Information" }, diff --git a/Source/CdrAuthServer.Repository/Configuration/GrantConfiguration.cs b/Source/CdrAuthServer.Repository/Configuration/GrantConfiguration.cs index 39ccab2..cf88b5f 100644 --- a/Source/CdrAuthServer.Repository/Configuration/GrantConfiguration.cs +++ b/Source/CdrAuthServer.Repository/Configuration/GrantConfiguration.cs @@ -19,8 +19,8 @@ public void Configure(EntityTypeBuilder builder) { Key = "12345678-1234-1234-1234-111122223333", ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", - CreatedAt = DateTime.UtcNow, - ExpiresAt = DateTime.UtcNow.AddDays(365), + CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc), + ExpiresAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddDays(365), GrantType = GrantTypes.CdrArrangement, SubjectId = "customer1", UsedAt = null, @@ -39,8 +39,8 @@ public void Configure(EntityTypeBuilder builder) // RefreshTokenGrant Key = refreshToken, ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", - CreatedAt = DateTime.UtcNow, - ExpiresAt = DateTime.UtcNow.AddDays(365), + CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc), + ExpiresAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddDays(365), GrantType = GrantTypes.RefreshToken, SubjectId = "customer1", UsedAt = null, @@ -56,8 +56,8 @@ public void Configure(EntityTypeBuilder builder) // RefreshTokenGrant2 Key = "expired-refresh-token", ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", - CreatedAt = DateTime.UtcNow.AddDays(-366), - ExpiresAt = DateTime.UtcNow.AddDays(-1), + CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddDays(-366), + ExpiresAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddDays(-1), GrantType = GrantTypes.RefreshToken, SubjectId = "customer1", UsedAt = null, @@ -65,7 +65,7 @@ public void Configure(EntityTypeBuilder builder) Data = JsonSerializer.Serialize(new Dictionary { { "response_type", ResponseTypes.AuthCode }, - { "CdrArrangementId", Guid.NewGuid().ToString() }, + { "CdrArrangementId", "87654321-4321-4321-4321-333344445555" }, }), }); } diff --git a/Source/CdrAuthServer.Repository/Migrations/20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates.Designer.cs b/Source/CdrAuthServer.Repository/Migrations/20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates.Designer.cs new file mode 100644 index 0000000..e2fd574 --- /dev/null +++ b/Source/CdrAuthServer.Repository/Migrations/20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates.Designer.cs @@ -0,0 +1,261 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace CdrAuthServer.Repository.Migrations +{ + [DbContext(typeof(CdrAuthServer.Repository.Infrastructure.CdrAuthServerDatabaseContext))] + [Migration("20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates")] + partial class V007_UpdateGrantSeedDataWithDeterministicDates + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("CdrAuthServer.Repository.Entities.Client", b => + { + b.Property("ClientId") + .HasColumnType("nvarchar(450)"); + + b.Property("ClientDescription") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientIdIssuedAt") + .HasColumnType("bigint"); + + b.Property("ClientName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("ClientId"); + + b.ToTable("Clients"); + + b.HasData( + new + { + ClientId = "11111111-1111-1111-1111-111111111111", + ClientIdIssuedAt = 0L, + ClientName = "Software Product 1" + }); + }); + + modelBuilder.Entity("CdrAuthServer.Repository.Entities.ClientClaims", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ClaimType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientClaims"); + + b.HasData( + new + { + Id = 1, + ClientId = "11111111-1111-1111-1111-111111111111", + ClaimType = "claim_type", + ClaimValue = "claim_value" + }); + }); + + modelBuilder.Entity("CdrAuthServer.Repository.Entities.Grant", b => + { + b.Property("Key") + .HasColumnType("nvarchar(450)"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("GrantType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Scope") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SubjectId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UsedAt") + .HasColumnType("datetime2"); + + b.HasKey("Key"); + + b.ToTable("Grants"); + + b.HasData( + new + { + Key = "12345678-1234-1234-1234-111122223333", + ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", + CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Data = "{\"refresh_token\":\"valid-refresh-token\",\"account_id\":[\"123\",\"456\",\"789\"]}", + ExpiresAt = new DateTime(2024, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), + GrantType = "cdr_arrangement", + Scope = "bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read energy:billing:read energy:electricity.servicepoints.basic:read energy:electricity.servicepoints.detail:read energy:electricity.usage:read energy:gas.servicepoints.basic:read energy:gas.servicepoints.detail:read energy:gas.usage:read telephone:accounts.basic:read telephone:accounts.detail:read telephone:usage:read water:accounts.basic:read water:accounts.detail:read water:usage:read common:customer.basic:read common:customer.detail:read", + SubjectId = "customer1" + }, + new + { + Key = "expired-refresh-token", + ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", + CreatedAt = new DateTime(2022, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), + Data = "{\"response_type\":\"code\",\"CdrArrangementId\":\"87654321-4321-4321-4321-333344445555\"}", + ExpiresAt = new DateTime(2023, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), + GrantType = "refresh_token", + Scope = "bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read", + SubjectId = "customer1" + }, + new + { + Key = "valid-refresh-token", + ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", + CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Data = "{\"response_type\":\"code\",\"CdrArrangementId\":\"12345678-1234-1234-1234-111122223333\"}", + ExpiresAt = new DateTime(2024, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), + GrantType = "refresh_token", + Scope = "bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read energy:billing:read energy:electricity.servicepoints.basic:read energy:electricity.servicepoints.detail:read energy:electricity.usage:read energy:gas.servicepoints.basic:read energy:gas.servicepoints.detail:read energy:gas.usage:read telephone:accounts.basic:read telephone:accounts.detail:read telephone:usage:read water:accounts.basic:read water:accounts.detail:read water:usage:read common:customer.basic:read common:customer.detail:read", + SubjectId = "customer1" + }); + }); + + modelBuilder.Entity("CdrAuthServer.Repository.Entities.SoftwareProduct", b => + { + b.Property("SoftwareProductId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("SoftwareProductId")); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("SoftwareProductDescription") + .HasColumnType("nvarchar(max)"); + + b.Property("SoftwareProductName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SoftwareProductStatus") + .HasColumnType("int"); + + b.HasKey("SoftwareProductId"); + + b.HasIndex("ClientId"); + + b.ToTable("SoftwareProducts"); + + b.HasData( + new + { + SoftwareProductId = 1, + ClientId = "11111111-1111-1111-1111-111111111111", + SoftwareProductDescription = "Software Product 1 Description", + SoftwareProductName = "Software Product 1", + SoftwareProductStatus = 1 + }, + new + { + SoftwareProductId = 2, + ClientId = "22222222-2222-2222-2222-222222222222", + SoftwareProductDescription = "Software Product 2 Description", + SoftwareProductName = "Software Product 2", + SoftwareProductStatus = 1 + }); + }); + + modelBuilder.Entity("CdrAuthServer.Repository.Entities.Token", b => + { + b.Property("Key") + .HasColumnType("nvarchar(450)"); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("SubjectId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TokenType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Key"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("CdrAuthServer.Repository.Entities.ClientClaims", b => + { + b.HasOne("CdrAuthServer.Repository.Entities.Client", null) + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("CdrAuthServer.Repository.Entities.SoftwareProduct", b => + { + b.HasOne("CdrAuthServer.Repository.Entities.Client", null) + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Source/CdrAuthServer.Repository/Migrations/20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates.cs b/Source/CdrAuthServer.Repository/Migrations/20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates.cs new file mode 100644 index 0000000..601bbb4 --- /dev/null +++ b/Source/CdrAuthServer.Repository/Migrations/20260812121516_V007_UpdateGrantSeedDataWithDeterministicDates.cs @@ -0,0 +1,61 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace CdrAuthServer.Repository.Migrations +{ + /// + public partial class V007_UpdateGrantSeedDataWithDeterministicDates : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Grants", + keyColumn: "Key", + keyValue: "12345678-1234-1234-1234-111122223333", + columns: new[] { "CreatedAt", "ExpiresAt" }, + values: new object[] { new DateTime(2024, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), new DateTime(2024, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc) }); + + migrationBuilder.UpdateData( + table: "Grants", + keyColumn: "Key", + keyValue: "expired-refresh-token", + columns: new[] { "CreatedAt", "Data", "ExpiresAt" }, + values: new object[] { new DateTime(2022, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), "{\"response_type\":\"code\",\"CdrArrangementId\":\"87654321-4321-4321-4321-333344445555\"}", new DateTime(2023, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc) }); + + migrationBuilder.UpdateData( + table: "Grants", + keyColumn: "Key", + keyValue: "valid-refresh-token", + columns: new[] { "CreatedAt", "ExpiresAt" }, + values: new object[] { new DateTime(2024, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), new DateTime(2024, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc) }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Grants", + keyColumn: "Key", + keyValue: "12345678-1234-1234-1234-111122223333", + columns: new[] { "CreatedAt", "ExpiresAt" }, + values: new object[] { new DateTime(2026, 5, 8, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(6478), new DateTime(2027, 5, 8, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(6481) }); + + migrationBuilder.UpdateData( + table: "Grants", + keyColumn: "Key", + keyValue: "expired-refresh-token", + columns: new[] { "CreatedAt", "Data", "ExpiresAt" }, + values: new object[] { new DateTime(2025, 5, 7, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(7048), "{\"response_type\":\"code\",\"CdrArrangementId\":\"bff2d629-cf6c-47e2-85ca-a30d0be8661d\"}", new DateTime(2026, 5, 7, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(7049) }); + + migrationBuilder.UpdateData( + table: "Grants", + keyColumn: "Key", + keyValue: "valid-refresh-token", + columns: new[] { "CreatedAt", "ExpiresAt" }, + values: new object[] { new DateTime(2026, 5, 8, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(7014), new DateTime(2027, 5, 8, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(7015) }); + } + } +} diff --git a/Source/CdrAuthServer.Repository/Migrations/CdrAuthServervDatabaseContextModelSnapshot.cs b/Source/CdrAuthServer.Repository/Migrations/CdrAuthServervDatabaseContextModelSnapshot.cs index 90afa19..c124ac3 100644 --- a/Source/CdrAuthServer.Repository/Migrations/CdrAuthServervDatabaseContextModelSnapshot.cs +++ b/Source/CdrAuthServer.Repository/Migrations/CdrAuthServervDatabaseContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("ProductVersion", "10.0.10") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -134,9 +134,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Key = "12345678-1234-1234-1234-111122223333", ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", - CreatedAt = new DateTime(2026, 5, 8, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(6478), + CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), Data = "{\"refresh_token\":\"valid-refresh-token\",\"account_id\":[\"123\",\"456\",\"789\"]}", - ExpiresAt = new DateTime(2027, 5, 8, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(6481), + ExpiresAt = new DateTime(2024, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), GrantType = "cdr_arrangement", Scope = "openid profile cdr:registration common:customer.basic:read common:customer.detail:read bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read energy:electricity.servicepoints.basic:read energy:electricity.servicepoints.detail:read energy:electricity.usage:read energy:electricity.der:read energy:accounts.basic:read energy:accounts.detail:read energy:accounts.paymentschedule:read energy:accounts.concessions:read energy:billing:read", SubjectId = "customer1" @@ -145,9 +145,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Key = "valid-refresh-token", ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", - CreatedAt = new DateTime(2026, 5, 8, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(7014), + CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), Data = "{\"response_type\":\"code\",\"CdrArrangementId\":\"12345678-1234-1234-1234-111122223333\"}", - ExpiresAt = new DateTime(2027, 5, 8, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(7015), + ExpiresAt = new DateTime(2024, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), GrantType = "refresh_token", Scope = "openid profile cdr:registration common:customer.basic:read common:customer.detail:read bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read energy:electricity.servicepoints.basic:read energy:electricity.servicepoints.detail:read energy:electricity.usage:read energy:electricity.der:read energy:accounts.basic:read energy:accounts.detail:read energy:accounts.paymentschedule:read energy:accounts.concessions:read energy:billing:read", SubjectId = "customer1" @@ -156,64 +156,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Key = "expired-refresh-token", ClientId = "c6327f87-687a-4369-99a4-eaacd3bb8210", - CreatedAt = new DateTime(2025, 5, 7, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(7048), - Data = "{\"response_type\":\"code\",\"CdrArrangementId\":\"bff2d629-cf6c-47e2-85ca-a30d0be8661d\"}", - ExpiresAt = new DateTime(2026, 5, 7, 3, 21, 37, 552, DateTimeKind.Utc).AddTicks(7049), + CreatedAt = new DateTime(2022, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), + Data = "{\"response_type\":\"code\",\"CdrArrangementId\":\"87654321-4321-4321-4321-333344445555\"}", + ExpiresAt = new DateTime(2023, 12, 31, 0, 0, 0, 0, DateTimeKind.Utc), GrantType = "refresh_token", Scope = "openid profile cdr:registration common:customer.basic:read common:customer.detail:read bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read", SubjectId = "customer1" }); }); - modelBuilder.Entity("CdrAuthServer.Repository.Entities.LogEventsDrService", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Environment") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("Exception") - .HasColumnType("nvarchar(max)"); - - b.Property("Level") - .HasColumnType("nvarchar(max)"); - - b.Property("Message") - .HasColumnType("nvarchar(max)"); - - b.Property("MethodName") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("ProcessId") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("ProcessName") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("SourceContext") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("ThreadId") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("TimeStamp") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.ToTable("LogEventsDrService"); - }); - modelBuilder.Entity("CdrAuthServer.Repository.Entities.SoftwareProduct", b => { b.Property("SoftwareProductId") diff --git a/Source/CdrAuthServer.UI/.nvmrc b/Source/CdrAuthServer.UI/.nvmrc new file mode 100644 index 0000000..471950d --- /dev/null +++ b/Source/CdrAuthServer.UI/.nvmrc @@ -0,0 +1 @@ +22.23.2 \ No newline at end of file diff --git a/Source/CdrAuthServer.UI/package-lock.json b/Source/CdrAuthServer.UI/package-lock.json index a88a303..6f35a4a 100644 --- a/Source/CdrAuthServer.UI/package-lock.json +++ b/Source/CdrAuthServer.UI/package-lock.json @@ -63,40 +63,6 @@ "node": ">=6.9.0" } }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@emotion/cache": { "version": "11.14.0", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", @@ -487,29 +453,10 @@ } } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, "node_modules/@oxc-project/types": { - "version": "0.133.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", - "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "version": "0.144.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.144.0.tgz", + "integrity": "sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==", "dev": true, "license": "MIT", "funding": { @@ -527,9 +474,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", - "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.4.tgz", + "integrity": "sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==", "cpu": [ "arm64" ], @@ -544,9 +491,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", - "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==", "cpu": [ "arm64" ], @@ -561,9 +508,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", - "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.4.tgz", + "integrity": "sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==", "cpu": [ "x64" ], @@ -578,9 +525,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", - "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.4.tgz", + "integrity": "sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==", "cpu": [ "x64" ], @@ -595,9 +542,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", - "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.4.tgz", + "integrity": "sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==", "cpu": [ "arm" ], @@ -612,16 +559,13 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", - "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.4.tgz", + "integrity": "sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==", "cpu": [ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -632,16 +576,13 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", - "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.4.tgz", + "integrity": "sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==", "cpu": [ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -652,16 +593,13 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", - "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.4.tgz", + "integrity": "sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==", "cpu": [ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -672,16 +610,13 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", - "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.4.tgz", + "integrity": "sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==", "cpu": [ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -692,16 +627,13 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", - "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.4.tgz", + "integrity": "sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==", "cpu": [ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -712,16 +644,13 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", - "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.4.tgz", + "integrity": "sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==", "cpu": [ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -732,9 +661,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", - "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.4.tgz", + "integrity": "sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==", "cpu": [ "arm64" ], @@ -748,29 +677,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", - "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", - "@napi-rs/wasm-runtime": "^1.1.4" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", - "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.4.tgz", + "integrity": "sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==", "cpu": [ "arm64" ], @@ -785,9 +695,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", - "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.4.tgz", + "integrity": "sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==", "cpu": [ "x64" ], @@ -940,17 +850,6 @@ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", "license": "MIT" }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", - "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/argparse": { "version": "1.0.38", "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", @@ -1224,16 +1123,16 @@ } }, "node_modules/ajv": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", - "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -1404,9 +1303,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { @@ -2209,6 +2108,23 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -2821,9 +2737,9 @@ } }, "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -2837,23 +2753,23 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", "cpu": [ "arm64" ], @@ -2872,9 +2788,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", "cpu": [ "arm64" ], @@ -2893,9 +2809,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", "cpu": [ "x64" ], @@ -2914,9 +2830,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", "cpu": [ "x64" ], @@ -2935,9 +2851,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", "cpu": [ "arm" ], @@ -2956,16 +2872,13 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", "cpu": [ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -2980,16 +2893,13 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", "cpu": [ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3004,16 +2914,13 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", "cpu": [ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3028,16 +2935,13 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", "cpu": [ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3052,9 +2956,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", "cpu": [ "arm64" ], @@ -3073,9 +2977,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", "cpu": [ "x64" ], @@ -3266,9 +3170,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { @@ -3613,9 +3517,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", "engines": { @@ -3649,9 +3553,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -3669,7 +3573,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -3737,16 +3641,6 @@ "safe-buffer": "^5.1.2" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/qs": { "version": "6.15.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", @@ -3870,9 +3764,9 @@ "license": "MIT" }, "node_modules/react-router": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.16.0.tgz", - "integrity": "sha512-wArC8lVyJb3+jM9OpDyW6hLCizACWkvQR/sSGqSs+o5uEXEtGlqdZ4v8hENR3Jad6i+LRkK93q/+bQAcvl6V1A==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.2.tgz", + "integrity": "sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -3892,12 +3786,12 @@ } }, "node_modules/react-router-dom": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.16.0.tgz", - "integrity": "sha512-kMUAbimWB5FVbF4Bce4bJsiKJWLIUHq/mEG8+CFDnCSgltptBiG5nguducmsJeGKytlCvQud9Qhzpn49iduTlA==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.2.tgz", + "integrity": "sha512-AIKJ/jgGlFb3EbfCXk5Gzshiwt+l3mqbCrNjmEWMMjqQxNJ3svBa6bgzFyCC2Sw3RA0VWF1kg3uQf2OFhxb8hw==", "license": "MIT", "dependencies": { - "react-router": "7.16.0" + "react-router": "7.18.2" }, "engines": { "node": ">=20.0.0" @@ -4088,13 +3982,13 @@ "license": "MIT" }, "node_modules/rolldown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", - "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.4.tgz", + "integrity": "sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.133.0", + "@oxc-project/types": "=0.144.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -4104,21 +3998,20 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.3", - "@rolldown/binding-darwin-arm64": "1.0.3", - "@rolldown/binding-darwin-x64": "1.0.3", - "@rolldown/binding-freebsd-x64": "1.0.3", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", - "@rolldown/binding-linux-arm64-gnu": "1.0.3", - "@rolldown/binding-linux-arm64-musl": "1.0.3", - "@rolldown/binding-linux-ppc64-gnu": "1.0.3", - "@rolldown/binding-linux-s390x-gnu": "1.0.3", - "@rolldown/binding-linux-x64-gnu": "1.0.3", - "@rolldown/binding-linux-x64-musl": "1.0.3", - "@rolldown/binding-openharmony-arm64": "1.0.3", - "@rolldown/binding-wasm32-wasi": "1.0.3", - "@rolldown/binding-win32-arm64-msvc": "1.0.3", - "@rolldown/binding-win32-x64-msvc": "1.0.3" + "@rolldown/binding-android-arm64": "1.2.4", + "@rolldown/binding-darwin-arm64": "1.2.4", + "@rolldown/binding-darwin-x64": "1.2.4", + "@rolldown/binding-freebsd-x64": "1.2.4", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.4", + "@rolldown/binding-linux-arm64-gnu": "1.2.4", + "@rolldown/binding-linux-arm64-musl": "1.2.4", + "@rolldown/binding-linux-ppc64-gnu": "1.2.4", + "@rolldown/binding-linux-s390x-gnu": "1.2.4", + "@rolldown/binding-linux-x64-gnu": "1.2.4", + "@rolldown/binding-linux-x64-musl": "1.2.4", + "@rolldown/binding-openharmony-arm64": "1.2.4", + "@rolldown/binding-win32-arm64-msvc": "1.2.4", + "@rolldown/binding-win32-x64-msvc": "1.2.4" } }, "node_modules/safe-buffer": { @@ -4600,14 +4493,6 @@ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", "license": "MIT" }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true - }, "node_modules/tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", @@ -4673,16 +4558,6 @@ "node": ">= 10.0.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/url": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", @@ -4726,30 +4601,29 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/vite": { - "version": "8.0.15", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.15.tgz", - "integrity": "sha512-qpgllRxrLqwsMAGRdLhsEr9bepaOQk1rxH1xT2coBXLaEB/bfkqQj1j7RMxwMfnYrvO1ZnFMiwX+wBVgnsyn0g==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", "dev": true, "license": "MIT", "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.4", - "postcss": "^8.5.15", - "rolldown": "1.0.3", + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.25", + "rolldown": "~1.2.1", "tinyglobby": "^0.2.17" }, "bin": { @@ -4766,7 +4640,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.18", + "@vitejs/devtools": "^0.4.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", diff --git a/Source/CdrAuthServer.UI/package.json b/Source/CdrAuthServer.UI/package.json index 02057a5..51ab87e 100644 --- a/Source/CdrAuthServer.UI/package.json +++ b/Source/CdrAuthServer.UI/package.json @@ -22,6 +22,10 @@ "styled-components": "^6.4.2", "yup": "^1.7.1" }, + "overrides":{ + "uuid": "11.1.1", + "ajv": "8.18.0" + }, "scripts": { "tsc": "tsc", "start": "vite", diff --git a/Source/CdrAuthServer.UnitTests/BaseTest.cs b/Source/CdrAuthServer.UnitTests/BaseTest.cs index a6a6507..4c5da01 100644 --- a/Source/CdrAuthServer.UnitTests/BaseTest.cs +++ b/Source/CdrAuthServer.UnitTests/BaseTest.cs @@ -46,7 +46,7 @@ public static string GetJwtToken(bool requireSS = false) aud = $"{DH_MTLS_GATEWAY_URL}/connect/token"; - var certificate = new X509Certificate2(JWT_CERTIFICATE_FILENAME, JWT_CERTIFICATE_PASSWORD, X509KeyStorageFlags.Exportable); + var certificate = X509CertificateLoader.LoadPkcs12FromFile(JWT_CERTIFICATE_FILENAME, JWT_CERTIFICATE_PASSWORD); var x509SigningCredentials = new X509SigningCredentials(certificate, SecurityAlgorithms.RsaSsaPssSha256); var jwt = new JwtSecurityToken( ISSUER, @@ -100,7 +100,7 @@ public static JwtSecurityToken GetJwt(string client_id = "", string RedirectUriV aud = $"{DH_MTLS_GATEWAY_URL}/connect/token"; - var certificate = new X509Certificate2(JWT_CERTIFICATE_FILENAME, JWT_CERTIFICATE_PASSWORD, X509KeyStorageFlags.Exportable); + var certificate = X509CertificateLoader.LoadPkcs12FromFile(JWT_CERTIFICATE_FILENAME, JWT_CERTIFICATE_PASSWORD); var x509SigningCredentials = new X509SigningCredentials(certificate, SecurityAlgorithms.RsaSsaPssSha256); var jwt = new JwtSecurityToken( ISSUER, diff --git a/Source/CdrAuthServer.UnitTests/Controllers/UtilityControllerTests.cs b/Source/CdrAuthServer.UnitTests/Controllers/UtilityControllerTests.cs index cac0014..c0b59c4 100644 --- a/Source/CdrAuthServer.UnitTests/Controllers/UtilityControllerTests.cs +++ b/Source/CdrAuthServer.UnitTests/Controllers/UtilityControllerTests.cs @@ -113,7 +113,7 @@ public async Task RemoveArrangementReturnsOKWithExceptionMessage(Type exceptionT // Assert ResultHelper.AssertInstanceOf(result, out var objResult); - ResultHelper.AssertJsonInstanceOf(objResult!, out var response); + ResultHelper.AssertJsonInstanceOf(objResult, out var response); AssertRequestIsPopulated(response.ArrangeRevocationRequest); @@ -142,7 +142,7 @@ public async Task RemoveArrangementReturnsOkForSuccessfullySendRequest(bool erro // Assert ResultHelper.AssertInstanceOf(result, out var objResult); - ResultHelper.AssertJsonInstanceOf(objResult!, out var response); + ResultHelper.AssertJsonInstanceOf(objResult, out var response); AssertRequestIsPopulated(response.ArrangeRevocationRequest); AssertResponseIsPopulated(response.ArrangeRevocationResponse, error); @@ -191,7 +191,7 @@ private static void AssertRequestIsPopulated(ArrangeRevocationRequest? arrangeRe { Assert.NotNull(arrangeRevocationRequest); Assert.NotNull(arrangeRevocationRequest!.Body); - Assert.That(Regex.IsMatch(arrangeRevocationRequest!.Body!, "cdr_arrangement_jwt=[\\w\\.]+")); + Assert.That(Regex.IsMatch(arrangeRevocationRequest.Body!, "cdr_arrangement_jwt=[\\w\\.]+")); Assert.AreEqual("POST", arrangeRevocationRequest.Method); Assert.AreEqual("https://localhost/arrangements/revoke", arrangeRevocationRequest.Url); Assert.IsNotEmpty(arrangeRevocationRequest.Headers); diff --git a/Source/CdrAuthServer.UnitTests/Helpers/HttpHelperTests.cs b/Source/CdrAuthServer.UnitTests/Helpers/HttpHelperTests.cs index 139d84d..1fde066 100644 --- a/Source/CdrAuthServer.UnitTests/Helpers/HttpHelperTests.cs +++ b/Source/CdrAuthServer.UnitTests/Helpers/HttpHelperTests.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using NUnit.Framework; using Serilog; using System; @@ -68,21 +69,25 @@ public MockEndpoint(string url, string certificatePath, string certificatePasswo public string CertificatePassword { get; init; } - private IWebHost? _host; + private IHost? _host; public void Start() { Log.Information("Calling {FUNCTION} in {ClassName}.", nameof(Start), nameof(MockEndpoint)); - _host = new WebHostBuilder() - .UseKestrel(opts => - { - opts.ListenAnyIP( - UrlPort, - opts => opts.UseHttps(new X509Certificate2(CertificatePath, CertificatePassword, X509KeyStorageFlags.Exportable))); - }) - .UseStartup(_ => new MockEndpointStartup()) - .Build(); + _host = Host.CreateDefaultBuilder() + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder + .UseKestrel(opts => + { + opts.ListenAnyIP( + UrlPort, + opts => opts.UseHttps(X509CertificateLoader.LoadPkcs12FromFile(CertificatePath, CertificatePassword))); + }) + .UseStartup(_ => new MockEndpointStartup()); + }) + .Build(); _host.RunAsync(); } diff --git a/Source/CdrAuthServer.UnitTests/ResultHelper.cs b/Source/CdrAuthServer.UnitTests/ResultHelper.cs index 49b7db8..b815d00 100644 --- a/Source/CdrAuthServer.UnitTests/ResultHelper.cs +++ b/Source/CdrAuthServer.UnitTests/ResultHelper.cs @@ -46,7 +46,7 @@ public static void AssertJsonInstanceOf(string value, out T instance) public static void AssertErrorExpectation(ObjectResult objectResult, string errorCode, string errorTitle, string errorDetail) { - Assert.IsInstanceOf(objectResult!.Value); + Assert.IsInstanceOf(objectResult.Value); var errors = objectResult.Value as ResponseErrorList; Assert.IsNotNull(errors); Assert.AreEqual(1, errors!.Errors.Count); diff --git a/Source/CdrAuthServer.UnitTests/Services/ConsentRevocationServiceTests.cs b/Source/CdrAuthServer.UnitTests/Services/ConsentRevocationServiceTests.cs index 72c89ba..a57237b 100644 --- a/Source/CdrAuthServer.UnitTests/Services/ConsentRevocationServiceTests.cs +++ b/Source/CdrAuthServer.UnitTests/Services/ConsentRevocationServiceTests.cs @@ -184,7 +184,7 @@ public async Task RevokeAdrArrangementCancelsOnParent() private async Task AssertBearerTokenIsValid(HttpRequestMessage request) { var handler = new JsonWebTokenHandler(); - var publicKey = new X509Certificate2(_ps256SigningCertificate.GetRawCertData()); + var publicKey = X509CertificateLoader.LoadCertificate(_ps256SigningCertificate.GetRawCertData()); var authHeader = request.Headers.Authorization; @@ -220,24 +220,25 @@ private async Task AssertBearerTokenIsValid(HttpRequestMessage request) private async Task AssertArrangementIsValid(HttpRequestMessage request) { var handler = new JsonWebTokenHandler(); - var publicKey = new X509Certificate2(_ps256SigningCertificate.GetRawCertData()); + var publicKey = X509CertificateLoader.LoadCertificate(_ps256SigningCertificate.GetRawCertData()); Assert.AreEqual("application/x-www-form-urlencoded", request.Content?.Headers.ContentType?.MediaType); - - using var reader = new Microsoft.AspNetCore.WebUtilities.FormReader(await request.Content!.ReadAsStreamAsync()); - var formValues = await reader.ReadFormAsync(); - - Assert.True(formValues.TryGetValue("cdr_arrangement_jwt", out StringValues cdrArrangementJwt)); - - var validationResult = await handler.ValidateTokenAsync(cdrArrangementJwt, new TokenValidationParameters + if (request.Content != null) { - ValidIssuer = _configurationOptions.Value.BrandId, - ValidAudience = _client.RecipientBaseUri + "/arrangements/revoke", - IssuerSigningKey = new X509SecurityKey(publicKey), - }); + using var reader = new Microsoft.AspNetCore.WebUtilities.FormReader(await request.Content.ReadAsStreamAsync()); + var formValues = await reader.ReadFormAsync(); - Assert.IsTrue(validationResult.IsValid, validationResult.Exception != null ? validationResult.Exception.Message : string.Empty); - Assert.AreEqual(_arrangementId, validationResult.Claims.FirstOrDefault(x => x.Key == "cdr_arrangement_id").Value); + Assert.True(formValues.TryGetValue("cdr_arrangement_jwt", out StringValues cdrArrangementJwt)); + var validationResult = await handler.ValidateTokenAsync(cdrArrangementJwt, new TokenValidationParameters + { + ValidIssuer = _configurationOptions.Value.BrandId, + ValidAudience = _client.RecipientBaseUri + "/arrangements/revoke", + IssuerSigningKey = new X509SecurityKey(publicKey), + }); + + Assert.IsTrue(validationResult.IsValid, validationResult.Exception != null ? validationResult.Exception.Message : string.Empty); + Assert.AreEqual(_arrangementId, validationResult.Claims.FirstOrDefault(x => x.Key == "cdr_arrangement_id").Value); + } } } } diff --git a/Source/CdrAuthServer.UnitTests/Services/RegisterClientServiceTests.cs b/Source/CdrAuthServer.UnitTests/Services/RegisterClientServiceTests.cs index d64f2a0..75662a5 100644 --- a/Source/CdrAuthServer.UnitTests/Services/RegisterClientServiceTests.cs +++ b/Source/CdrAuthServer.UnitTests/Services/RegisterClientServiceTests.cs @@ -119,7 +119,7 @@ public async Task GetDataRecipientsReturnsLegalEntitiesForSuccessfulRequest() // Assert Assert.IsNotNull(result); Assert.AreEqual(1, result!.Data.Count()); - Assert.AreEqual("https://localhost/cdr-register/v1/all/data-recipients", result!.Links.Self?.AbsoluteUri); + Assert.AreEqual("https://localhost/cdr-register/v1/all/data-recipients", result.Links.Self?.AbsoluteUri); _mockHttpClient.VerifyAll(); } } diff --git a/Source/CdrAuthServer.UnitTests/Validators/ClientAssertionValidatorTests.cs b/Source/CdrAuthServer.UnitTests/Validators/ClientAssertionValidatorTests.cs index d40a675..0d38f3f 100644 --- a/Source/CdrAuthServer.UnitTests/Validators/ClientAssertionValidatorTests.cs +++ b/Source/CdrAuthServer.UnitTests/Validators/ClientAssertionValidatorTests.cs @@ -115,7 +115,7 @@ public async Task Validate_ClientAssertionRequest_InvalidClient_Test( aud = $"{DH_MTLS_GATEWAY_URL}/connect/token"; - var certificate = new X509Certificate2(JWT_CERTIFICATE_FILENAME, JWT_CERTIFICATE_PASSWORD, X509KeyStorageFlags.Exportable); + var certificate = X509CertificateLoader.LoadPkcs12FromFile(JWT_CERTIFICATE_FILENAME, JWT_CERTIFICATE_PASSWORD); var x509SigningCredentials = new X509SigningCredentials(certificate, SecurityAlgorithms.RsaSsaPssSha256); var jwt = new JwtSecurityToken( ISSUER, diff --git a/Source/CdrAuthServer.mTLS.Gateway/Certificates/CertificateValidator.cs b/Source/CdrAuthServer.mTLS.Gateway/Certificates/CertificateValidator.cs index c633479..81a8a88 100644 --- a/Source/CdrAuthServer.mTLS.Gateway/Certificates/CertificateValidator.cs +++ b/Source/CdrAuthServer.mTLS.Gateway/Certificates/CertificateValidator.cs @@ -32,7 +32,7 @@ public void ValidateClientCertificate(X509Certificate2 clientCert) } // Validate that the certificate has been issued by the Mock CDR CA. - var rootCACertificate = new X509Certificate2(rootCertLocation); + var rootCACertificate = X509CertificateLoader.LoadCertificateFromFile(rootCertLocation); _logger.LogDebug("Validating client certificate using: {RootCACertificate}", rootCACertificate); var ch = new X509Chain(); diff --git a/Source/CdrAuthServer.sln b/Source/CdrAuthServer.sln deleted file mode 100644 index 9c1985f..0000000 --- a/Source/CdrAuthServer.sln +++ /dev/null @@ -1,119 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32210.238 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer", "CdrAuthServer\CdrAuthServer.csproj", "{78665DD1-DF8B-42BE-A4EF-E515081DD34D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Artefacts", "Artefacts", "{2BA365FC-FFCC-449A-96B5-BC73D9216FB1}" - ProjectSection(SolutionItems) = preProject - .dockerignore = .dockerignore - .editorconfig = .editorconfig - ..\.gitignore = ..\.gitignore - docker-compose.E2ETests.Standalone.yml = docker-compose.E2ETests.Standalone.yml - docker-compose.E2ETests.yml = docker-compose.E2ETests.yml - docker-compose.IntegrationTests.Standalone.yml = docker-compose.IntegrationTests.Standalone.yml - docker-compose.IntegrationTests.yml = docker-compose.IntegrationTests.yml - Dockerfile = Dockerfile - Dockerfile.e2e-tests = Dockerfile.e2e-tests - Dockerfile.integration-tests = Dockerfile.integration-tests - Dockerfile.standalone = Dockerfile.standalone - Dockerfile.unit-tests = Dockerfile.unit-tests - ..\README.md = ..\README.md - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.mTLS.Gateway", "CdrAuthServer.mTLS.Gateway\CdrAuthServer.mTLS.Gateway.csproj", "{61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.TLS.Gateway", "CdrAuthServer.TLS.Gateway\CdrAuthServer.TLS.Gateway.csproj", "{46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.Infrastructure", "CdrAuthServer.Infrastructure\CdrAuthServer.Infrastructure.csproj", "{7610AD7D-D77C-453D-9CF2-31A445927CBD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.UnitTests", "CdrAuthServer.UnitTests\CdrAuthServer.UnitTests.csproj", "{86B921A4-D074-4EF1-993C-9D20CD977626}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.Repository", "CdrAuthServer.Repository\CdrAuthServer.Repository.csproj", "{0C879BF9-BD17-4345-A1C5-6155DAA77201}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{298CB3D0-DE65-4972-A45A-4E8BF0CE2EEC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.Domain", "CdrAuthServer.Domain\CdrAuthServer.Domain.csproj", "{6F969FE7-22B0-4934-BB78-E2DC851FD6B7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.IntegrationTests", "CdrAuthServer.IntegrationTests\CdrAuthServer.IntegrationTests.csproj", "{F1146EC8-2571-4A4C-A1E2-B4173F28BF72}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.E2ETests", "CdrAuthServer.E2ETests\CdrAuthServer.E2ETests.csproj", "{FB0EAE35-BFBC-444E-B575-9093340DB740}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.API.Logger", "CdrAuthServer.API.Logger\CdrAuthServer.API.Logger.csproj", "{4938DCAE-5403-4ABF-A383-5814F6174E86}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.GetDataRecipients", "CdrAuthServer.GetDataRecipients\CdrAuthServer.GetDataRecipients.csproj", "{15414FBE-A899-4670-833A-54C9496717F6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.GetDataRecipients.IntegrationTests", "CdrAuthServer.GetDataRecipients.IntegrationTests\CdrAuthServer.GetDataRecipients.IntegrationTests.csproj", "{56C795F0-376A-4938-9552-A037AD231EFD}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" - ProjectSection(SolutionItems) = preProject - Directory.Build.props = Directory.Build.props - Directory.Packages.props = Directory.Packages.props - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Release|Any CPU.Build.0 = Release|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Release|Any CPU.Build.0 = Release|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Debug|Any CPU.Build.0 = Debug|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Release|Any CPU.ActiveCfg = Release|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Release|Any CPU.Build.0 = Release|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Release|Any CPU.Build.0 = Release|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Release|Any CPU.Build.0 = Release|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Release|Any CPU.Build.0 = Release|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Release|Any CPU.Build.0 = Release|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Release|Any CPU.Build.0 = Release|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Release|Any CPU.Build.0 = Release|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Release|Any CPU.Build.0 = Release|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Release|Any CPU.Build.0 = Release|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7} = {298CB3D0-DE65-4972-A45A-4E8BF0CE2EEC} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {B504E2EB-E273-47C9-BAF7-6229989FA3AB} - EndGlobalSection -EndGlobal diff --git a/Source/CdrAuthServer.slnx b/Source/CdrAuthServer.slnx new file mode 100644 index 0000000..a43b951 --- /dev/null +++ b/Source/CdrAuthServer.slnx @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/CdrAuthServer/CdrAuthServer.csproj b/Source/CdrAuthServer/CdrAuthServer.csproj index 7ed469c..c546270 100644 --- a/Source/CdrAuthServer/CdrAuthServer.csproj +++ b/Source/CdrAuthServer/CdrAuthServer.csproj @@ -40,6 +40,7 @@ + diff --git a/Source/CdrAuthServer/Controllers/AdminController.cs b/Source/CdrAuthServer/Controllers/AdminController.cs index 05b4a2e..df248c4 100644 --- a/Source/CdrAuthServer/Controllers/AdminController.cs +++ b/Source/CdrAuthServer/Controllers/AdminController.cs @@ -1,4 +1,5 @@ -using CdrAuthServer.Authorisation; +using Asp.Versioning; +using CdrAuthServer.Authorisation; using CdrAuthServer.Configuration; using CdrAuthServer.Infrastructure; using CdrAuthServer.Infrastructure.Attributes; diff --git a/Source/CdrAuthServer/Controllers/ArrangementRevocationController.cs b/Source/CdrAuthServer/Controllers/ArrangementRevocationController.cs index 315f940..d92cf13 100644 --- a/Source/CdrAuthServer/Controllers/ArrangementRevocationController.cs +++ b/Source/CdrAuthServer/Controllers/ArrangementRevocationController.cs @@ -1,4 +1,5 @@ -using CdrAuthServer.Domain.Models; +using Asp.Versioning; +using CdrAuthServer.Domain.Models; using CdrAuthServer.Extensions; using CdrAuthServer.Infrastructure.Models; using CdrAuthServer.Models; diff --git a/Source/CdrAuthServer/Controllers/AuthorisationController.cs b/Source/CdrAuthServer/Controllers/AuthorisationController.cs index b311568..249468e 100644 --- a/Source/CdrAuthServer/Controllers/AuthorisationController.cs +++ b/Source/CdrAuthServer/Controllers/AuthorisationController.cs @@ -1,6 +1,7 @@ using System.Security.Claims; using System.Text; using System.Web; +using Asp.Versioning; using CdrAuthServer.Configuration; using CdrAuthServer.Extensions; using CdrAuthServer.Models; diff --git a/Source/CdrAuthServer/Controllers/DiscoveryController.cs b/Source/CdrAuthServer/Controllers/DiscoveryController.cs index 30ac529..9e4f7d0 100644 --- a/Source/CdrAuthServer/Controllers/DiscoveryController.cs +++ b/Source/CdrAuthServer/Controllers/DiscoveryController.cs @@ -1,4 +1,5 @@ -using CdrAuthServer.Extensions; +using Asp.Versioning; +using CdrAuthServer.Extensions; using CdrAuthServer.Models; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; diff --git a/Source/CdrAuthServer/Controllers/IntrospectionController.cs b/Source/CdrAuthServer/Controllers/IntrospectionController.cs index b7d04c0..f737f60 100644 --- a/Source/CdrAuthServer/Controllers/IntrospectionController.cs +++ b/Source/CdrAuthServer/Controllers/IntrospectionController.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.IdentityModel.Tokens.Jwt; +using Asp.Versioning; using CdrAuthServer.Extensions; using CdrAuthServer.Models; using CdrAuthServer.Services; diff --git a/Source/CdrAuthServer/Controllers/JwksController.cs b/Source/CdrAuthServer/Controllers/JwksController.cs index 3f5b778..8cc3ab2 100644 --- a/Source/CdrAuthServer/Controllers/JwksController.cs +++ b/Source/CdrAuthServer/Controllers/JwksController.cs @@ -1,5 +1,6 @@ using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; +using Asp.Versioning; using CdrAuthServer.Extensions; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; diff --git a/Source/CdrAuthServer/Controllers/PushedAuthorisationController.cs b/Source/CdrAuthServer/Controllers/PushedAuthorisationController.cs index 7ba9398..601e7c2 100644 --- a/Source/CdrAuthServer/Controllers/PushedAuthorisationController.cs +++ b/Source/CdrAuthServer/Controllers/PushedAuthorisationController.cs @@ -1,4 +1,5 @@ -using CdrAuthServer.Domain; +using Asp.Versioning; +using CdrAuthServer.Domain; using CdrAuthServer.Domain.Models; using CdrAuthServer.Extensions; using CdrAuthServer.Models; diff --git a/Source/CdrAuthServer/Controllers/RegistrationController.cs b/Source/CdrAuthServer/Controllers/RegistrationController.cs index 7bc4323..ae0b3da 100644 --- a/Source/CdrAuthServer/Controllers/RegistrationController.cs +++ b/Source/CdrAuthServer/Controllers/RegistrationController.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using Asp.Versioning; using CdrAuthServer.Authorisation; using CdrAuthServer.Configuration; using CdrAuthServer.Extensions; diff --git a/Source/CdrAuthServer/Controllers/ResourceController.cs b/Source/CdrAuthServer/Controllers/ResourceController.cs index 9415aa8..4e180be 100644 --- a/Source/CdrAuthServer/Controllers/ResourceController.cs +++ b/Source/CdrAuthServer/Controllers/ResourceController.cs @@ -1,4 +1,5 @@ -using CdrAuthServer.Authorisation; +using Asp.Versioning; +using CdrAuthServer.Authorisation; using CdrAuthServer.Extensions; using CdrAuthServer.Infrastructure.Attributes; using CdrAuthServer.Infrastructure.Authorisation; diff --git a/Source/CdrAuthServer/Controllers/RevocationController.cs b/Source/CdrAuthServer/Controllers/RevocationController.cs index 6b36ba6..c56236c 100644 --- a/Source/CdrAuthServer/Controllers/RevocationController.cs +++ b/Source/CdrAuthServer/Controllers/RevocationController.cs @@ -1,4 +1,5 @@ using System.IdentityModel.Tokens.Jwt; +using Asp.Versioning; using CdrAuthServer.Extensions; using CdrAuthServer.Services; using CdrAuthServer.Validation; diff --git a/Source/CdrAuthServer/Controllers/TokenController.cs b/Source/CdrAuthServer/Controllers/TokenController.cs index 3d8f98d..72dfb3b 100644 --- a/Source/CdrAuthServer/Controllers/TokenController.cs +++ b/Source/CdrAuthServer/Controllers/TokenController.cs @@ -1,4 +1,5 @@ -using CdrAuthServer.Extensions; +using Asp.Versioning; +using CdrAuthServer.Extensions; using CdrAuthServer.Models; using CdrAuthServer.Services; using CdrAuthServer.Validation; diff --git a/Source/CdrAuthServer/Controllers/UserInfoController.cs b/Source/CdrAuthServer/Controllers/UserInfoController.cs index efc0292..6162c42 100644 --- a/Source/CdrAuthServer/Controllers/UserInfoController.cs +++ b/Source/CdrAuthServer/Controllers/UserInfoController.cs @@ -1,4 +1,5 @@ -using CdrAuthServer.Authorisation; +using Asp.Versioning; +using CdrAuthServer.Authorisation; using CdrAuthServer.Extensions; using CdrAuthServer.Infrastructure.Authorisation; using CdrAuthServer.Models; diff --git a/Source/CdrAuthServer/Controllers/UtilityController.cs b/Source/CdrAuthServer/Controllers/UtilityController.cs index feab689..1836ba8 100644 --- a/Source/CdrAuthServer/Controllers/UtilityController.cs +++ b/Source/CdrAuthServer/Controllers/UtilityController.cs @@ -1,4 +1,5 @@ using System.Net; +using Asp.Versioning; using CdrAuthServer.Domain.Models; using CdrAuthServer.Extensions; using CdrAuthServer.Models; diff --git a/Source/CdrAuthServer/Extensions/SwaggerExtensions.cs b/Source/CdrAuthServer/Extensions/SwaggerExtensions.cs index fb66c19..921a78e 100644 --- a/Source/CdrAuthServer/Extensions/SwaggerExtensions.cs +++ b/Source/CdrAuthServer/Extensions/SwaggerExtensions.cs @@ -1,4 +1,5 @@ -using CdrAuthServer.Infrastructure.Configuration; +using Asp.Versioning; +using CdrAuthServer.Infrastructure.Configuration; using CdrAuthServer.Infrastructure.Models; using CdrAuthServer.SwaggerFilters; using Microsoft.Extensions.Options; @@ -21,10 +22,15 @@ public static IServiceCollection AddCdrSwaggerGen(this IServiceCollection servic services.AddTransient, ConfigureSwaggerOptions>(); // Required for our Swagger setup to work when endpoints have been versioned - services.AddVersionedApiExplorer(opt => - { - opt.GroupNameFormat = options.VersionedApiGroupNameFormat; - }); + services.AddApiVersioning(versioningOptions => + { + versioningOptions.ApiVersionReader = new QueryStringApiVersionReader(); + }) + .AddMvc() + .AddApiExplorer(opt => + { + opt.GroupNameFormat = options.VersionedApiGroupNameFormat; + }); } else { diff --git a/Source/CdrAuthServer/IdPermanence/IdPermanenceHelper.cs b/Source/CdrAuthServer/IdPermanence/IdPermanenceHelper.cs index 8ecfe62..09e4ad9 100644 --- a/Source/CdrAuthServer/IdPermanence/IdPermanenceHelper.cs +++ b/Source/CdrAuthServer/IdPermanence/IdPermanenceHelper.cs @@ -210,7 +210,7 @@ public static string GetPrivateKey(IConfiguration config) throw new ConfigurationErrorsException($"The private key was not found in configuration. Either set the \"IdPermanence:PrivateKey\" configuration item or the \"IdPermanence:Certificate:Path\" and \"IdPermanence:Certificate:Password\" configuration items to load the private key."); } - var cert = new X509Certificate2(path, pwd, X509KeyStorageFlags.Exportable); + var cert = X509CertificateLoader.LoadPkcs12FromFile(path, pwd, X509KeyStorageFlags.Exportable); return new string(cert.GetRSAPrivateKey()?.ExportPkcs8PrivateKey().Select(b => Convert.ToChar(b)).ToArray()); } } diff --git a/Source/CdrAuthServer/Program.cs b/Source/CdrAuthServer/Program.cs index 2aae1e1..9bdb290 100644 --- a/Source/CdrAuthServer/Program.cs +++ b/Source/CdrAuthServer/Program.cs @@ -179,9 +179,11 @@ await builder.Services.ConfigureWebServer( "AllOrigins", policy => { +#pragma warning disable S5122 // Cross-Origin Resource Sharing (CORS) policy should be restricted to trusted origins policy.WithOrigins("*") .AllowAnyHeader() .AllowAnyMethod(); +#pragma warning restore S5122 // Cross-Origin Resource Sharing (CORS) policy should be restricted to trusted origins }); }); @@ -208,7 +210,7 @@ await builder.Services.ConfigureWebServer( builder.Services.AddTransient(); builder.Services.AddTransient(); -builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); +builder.Services.AddAutoMapper(cfg => { }, AppDomain.CurrentDomain.GetAssemblies()); builder.Services.AddScoped(); builder.Services.AddHttpClient(); diff --git a/Source/CdrAuthServer/Services/ConsentRevocationService.cs b/Source/CdrAuthServer/Services/ConsentRevocationService.cs index d632c19..f51e226 100644 --- a/Source/CdrAuthServer/Services/ConsentRevocationService.cs +++ b/Source/CdrAuthServer/Services/ConsentRevocationService.cs @@ -73,7 +73,7 @@ public async Task RevokeAdrArrangementsForSoftwareProducts(IEnumerable s logger.LogInformation("Calling ADR Arrangement revocation endpoint for arrangement {Arrangement} and client {@Client}", a.ArrangementId, client); var result = await RevokeAdrArrangement(client, a.ArrangementId, revocationTimeout, cancellationToken); - if (result.Response is null || !result.Response!.IsSuccessStatusCode) + if (result.Response is null || !result.Response.IsSuccessStatusCode) { #pragma warning disable S112 // General or reserved exceptions should never be thrown throw new Exception($"Unable to revoke arrangement {a.ArrangementId} with ADR"); diff --git a/Source/CdrAuthServer/Services/TokenService.cs b/Source/CdrAuthServer/Services/TokenService.cs index 30c87d1..c265382 100644 --- a/Source/CdrAuthServer/Services/TokenService.cs +++ b/Source/CdrAuthServer/Services/TokenService.cs @@ -488,7 +488,7 @@ private async Task GetAuthCodeTokenResponse(TokenRequest tokenReq authCodeGrant.SubjectId, configOptions, authCode: authCodeGrant.Key, - nonce: authRequestObject!.Nonce, + nonce: authRequestObject.Nonce, accessToken: accessToken, authTime: authTime.ToEpoch().ToString()); } diff --git a/Source/CdrAuthServer/Validation/ValidateMtlsAttribute.cs b/Source/CdrAuthServer/Validation/ValidateMtlsAttribute.cs index 3ca75a3..41d48f0 100644 --- a/Source/CdrAuthServer/Validation/ValidateMtlsAttribute.cs +++ b/Source/CdrAuthServer/Validation/ValidateMtlsAttribute.cs @@ -71,7 +71,7 @@ private void VerifyCertificateRevocation(ActionExecutingContext context, Configu _logger.LogInformation("Cert after cleanup for OCSP - {Processed}", processedCertString); // Load the certificate into an X509Certificate object. - var cert = new X509Certificate2(processedCertString); + var cert = X509CertificateLoader.LoadCertificate(processedCertString); try { diff --git a/Source/CdrAuthServer_Shared.sln b/Source/CdrAuthServer_Shared.sln deleted file mode 100644 index fc9d963..0000000 --- a/Source/CdrAuthServer_Shared.sln +++ /dev/null @@ -1,151 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32210.238 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer", "CdrAuthServer\CdrAuthServer.csproj", "{78665DD1-DF8B-42BE-A4EF-E515081DD34D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Artefacts", "Artefacts", "{2BA365FC-FFCC-449A-96B5-BC73D9216FB1}" - ProjectSection(SolutionItems) = preProject - .dockerignore = .dockerignore - ..\.gitignore = ..\.gitignore - docker-compose.E2ETests.Standalone.yml = docker-compose.E2ETests.Standalone.yml - docker-compose.E2ETests.yml = docker-compose.E2ETests.yml - docker-compose.IntegrationTests.Standalone.yml = docker-compose.IntegrationTests.Standalone.yml - docker-compose.IntegrationTests.yml = docker-compose.IntegrationTests.yml - Dockerfile = Dockerfile - Dockerfile.e2e-tests = Dockerfile.e2e-tests - Dockerfile.integration-tests = Dockerfile.integration-tests - Dockerfile.standalone = Dockerfile.standalone - Dockerfile.unit-tests = Dockerfile.unit-tests - ..\README.md = ..\README.md - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.mTLS.Gateway", "CdrAuthServer.mTLS.Gateway\CdrAuthServer.mTLS.Gateway.csproj", "{61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.TLS.Gateway", "CdrAuthServer.TLS.Gateway\CdrAuthServer.TLS.Gateway.csproj", "{46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.Infrastructure", "CdrAuthServer.Infrastructure\CdrAuthServer.Infrastructure.csproj", "{7610AD7D-D77C-453D-9CF2-31A445927CBD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.UnitTests", "CdrAuthServer.UnitTests\CdrAuthServer.UnitTests.csproj", "{86B921A4-D074-4EF1-993C-9D20CD977626}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.Repository", "CdrAuthServer.Repository\CdrAuthServer.Repository.csproj", "{0C879BF9-BD17-4345-A1C5-6155DAA77201}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{298CB3D0-DE65-4972-A45A-4E8BF0CE2EEC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.Domain", "CdrAuthServer.Domain\CdrAuthServer.Domain.csproj", "{6F969FE7-22B0-4934-BB78-E2DC851FD6B7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.IntegrationTests", "CdrAuthServer.IntegrationTests\CdrAuthServer.IntegrationTests.csproj", "{F1146EC8-2571-4A4C-A1E2-B4173F28BF72}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.E2ETests", "CdrAuthServer.E2ETests\CdrAuthServer.E2ETests.csproj", "{FB0EAE35-BFBC-444E-B575-9093340DB740}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E43B55CB-B68B-4733-81A4-B293FD01C4F1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.API.Logger", "CdrAuthServer.API.Logger\CdrAuthServer.API.Logger.csproj", "{4938DCAE-5403-4ABF-A383-5814F6174E86}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.GetDataRecipients", "CdrAuthServer.GetDataRecipients\CdrAuthServer.GetDataRecipients.csproj", "{15414FBE-A899-4670-833A-54C9496717F6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CdrAuthServer.GetDataRecipients.IntegrationTests", "CdrAuthServer.GetDataRecipients.IntegrationTests\CdrAuthServer.GetDataRecipients.IntegrationTests.csproj", "{56C795F0-376A-4938-9552-A037AD231EFD}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestAutomation", "TestAutomation", "{B3C76970-A640-4130-80C2-1918D4BCD662}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{881CE210-FC0B-4CC3-9E61-1B551AF83934}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation", "..\..\sb-mock-solution-test-automation\Source\ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation\ConsumerDataRight.ParticipantTooling.MockSolution.TestAutomation.csproj", "{82BCDF1B-CE46-4802-88B0-12A448EE25FF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - Shared|Any CPU = Shared|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Release|Any CPU.Build.0 = Release|Any CPU - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {78665DD1-DF8B-42BE-A4EF-E515081DD34D}.Shared|Any CPU.Build.0 = Release|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Release|Any CPU.Build.0 = Release|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {61E25B6D-F15F-4B81-8F29-7A9BB85A9D0D}.Shared|Any CPU.Build.0 = Release|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Debug|Any CPU.Build.0 = Debug|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Release|Any CPU.ActiveCfg = Release|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Release|Any CPU.Build.0 = Release|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {46E37BFF-E5FD-4974-AA3D-753F7BDEFB57}.Shared|Any CPU.Build.0 = Release|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Release|Any CPU.Build.0 = Release|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {7610AD7D-D77C-453D-9CF2-31A445927CBD}.Shared|Any CPU.Build.0 = Release|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Release|Any CPU.Build.0 = Release|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {86B921A4-D074-4EF1-993C-9D20CD977626}.Shared|Any CPU.Build.0 = Release|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Release|Any CPU.Build.0 = Release|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {0C879BF9-BD17-4345-A1C5-6155DAA77201}.Shared|Any CPU.Build.0 = Release|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Release|Any CPU.Build.0 = Release|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7}.Shared|Any CPU.Build.0 = Release|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Release|Any CPU.Build.0 = Release|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Shared|Any CPU.ActiveCfg = Shared|Any CPU - {F1146EC8-2571-4A4C-A1E2-B4173F28BF72}.Shared|Any CPU.Build.0 = Shared|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Release|Any CPU.Build.0 = Release|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Shared|Any CPU.ActiveCfg = Shared|Any CPU - {FB0EAE35-BFBC-444E-B575-9093340DB740}.Shared|Any CPU.Build.0 = Shared|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Release|Any CPU.Build.0 = Release|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {4938DCAE-5403-4ABF-A383-5814F6174E86}.Shared|Any CPU.Build.0 = Release|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Release|Any CPU.Build.0 = Release|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {15414FBE-A899-4670-833A-54C9496717F6}.Shared|Any CPU.Build.0 = Release|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Release|Any CPU.Build.0 = Release|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {56C795F0-376A-4938-9552-A037AD231EFD}.Shared|Any CPU.Build.0 = Release|Any CPU - {82BCDF1B-CE46-4802-88B0-12A448EE25FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {82BCDF1B-CE46-4802-88B0-12A448EE25FF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {82BCDF1B-CE46-4802-88B0-12A448EE25FF}.Shared|Any CPU.ActiveCfg = Release|Any CPU - {82BCDF1B-CE46-4802-88B0-12A448EE25FF}.Shared|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {6F969FE7-22B0-4934-BB78-E2DC851FD6B7} = {298CB3D0-DE65-4972-A45A-4E8BF0CE2EEC} - {B3C76970-A640-4130-80C2-1918D4BCD662} = {881CE210-FC0B-4CC3-9E61-1B551AF83934} - {82BCDF1B-CE46-4802-88B0-12A448EE25FF} = {B3C76970-A640-4130-80C2-1918D4BCD662} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {B504E2EB-E273-47C9-BAF7-6229989FA3AB} - EndGlobalSection -EndGlobal diff --git a/Source/CdrAuthServer_Shared.slnx b/Source/CdrAuthServer_Shared.slnx new file mode 100644 index 0000000..5d9d1c7 --- /dev/null +++ b/Source/CdrAuthServer_Shared.slnx @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Directory.Build.props b/Source/Directory.Build.props index ae254fd..17a72f0 100644 --- a/Source/Directory.Build.props +++ b/Source/Directory.Build.props @@ -1,7 +1,7 @@ - - net8.0 - 3.1.0 + + net10.0 + 3.2.0 true true true diff --git a/Source/Directory.Packages.props b/Source/Directory.Packages.props index 02c3257..4923f4e 100644 --- a/Source/Directory.Packages.props +++ b/Source/Directory.Packages.props @@ -6,50 +6,50 @@ $(NoWarn);NU1507 - + - + - + + - - - - - - - + + + + + + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - + - + - + @@ -58,19 +58,21 @@ - + - + - + - - - - + + + + + + diff --git a/Source/Dockerfile b/Source/Dockerfile index 065d088..ebe87ba 100644 --- a/Source/Dockerfile +++ b/Source/Dockerfile @@ -4,7 +4,7 @@ ############################################################################### # Build base layer ############################################################################### -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base WORKDIR /app EXPOSE 8081 @@ -14,7 +14,7 @@ ENV ASPNETCORE_ENVIRONMENT=Release ############################################################################### # Build CdrAuthServer API layer ############################################################################### -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src COPY ./ . @@ -60,18 +60,13 @@ RUN apt-get update \ RUN sudo cp ./gateway-mtls/Certificates/ca.crt /usr/local/share/ca-certificates/ca.crt \ && sudo update-ca-certificates -RUN addgroup --group appgroup --gid 2000 \ - && adduser --uid 1000 --gid 2000 "appuser" \ - && chown -R appuser:appgroup /app \ - && chown -R appuser:appgroup /usr/bin \ - && chown -R appuser:appgroup /usr/local \ - && chown -R appuser:appgroup /tmp +RUN chown -R app:app /app -USER appuser:appgroup +USER app ENV ASPNETCORE_URLS=https://+:8081;https://+:8082 ENV CdrAuthServer__HttpsPort=8001 ENV CdrAuthServer__HttpPort=8080 # Entry point ################################################################# -ENTRYPOINT ["/usr/bin/supervisord", "-c", "/app/supervisord.conf", "-u", "1000"] +ENTRYPOINT ["/usr/bin/supervisord", "-c", "/app/supervisord.conf"] diff --git a/Source/Dockerfile.e2e-tests b/Source/Dockerfile.e2e-tests index 7d20687..e33ffed 100644 --- a/Source/Dockerfile.e2e-tests +++ b/Source/Dockerfile.e2e-tests @@ -1,8 +1,9 @@ # Dockerfile for E2E tests # NB: Ensure playwright version used in the ConsumerDataRight.ParticipantTooling.Shared.TestAutomation NuGet package and base image below are same (ie currently 1.43.0) -# Playwright jammy for .Net 8 -FROM mcr.microsoft.com/playwright/dotnet:v1.43.0-jammy as build + +# Playwright noble for .Net 10 +FROM mcr.microsoft.com/playwright/dotnet:v1.62.0-noble as build ############################################################################### # Build E2E tests diff --git a/Source/Dockerfile.get-data-recipients b/Source/Dockerfile.get-data-recipients index 846e051..33da608 100644 --- a/Source/Dockerfile.get-data-recipients +++ b/Source/Dockerfile.get-data-recipients @@ -1,6 +1,6 @@ # Dockerfile for running GetDataRecipients for integration testing # Use .Net 8 to build function app -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build # Setup Crediential Provider to allow access to Azure Artifact Feed for accessing Nuget Package RUN curl -L https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | sh @@ -18,11 +18,11 @@ ARG BUILD_CONFIGURATION=Release RUN dotnet restore RUN dotnet build /p:DefineConstants="INTEGRATION_TESTS" -c $BUILD_CONFIGURATION -# Use .Net 8 isolated image to host function app -FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated8.0 AS final +# Use .Net 10 isolated image to host function app +FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated10.0 AS final # Copy required files from build stage -COPY --from=build /src/CdrAuthServer.GetDataRecipients/bin/Release/net8.0/. /home/site/wwwroot +COPY --from=build /src/CdrAuthServer.GetDataRecipients/bin/Release/net10.0/. /home/site/wwwroot COPY --from=build /src/CdrAuthServer.GetDataRecipients/local.settings.json /azure-functions-host/local.settings.json COPY --from=build /src/CdrAuthServer.GetDataRecipients/appsettings.docker.json /azure-functions-host/appsettings.docker.json COPY --from=build /src/CdrAuthServer.GetDataRecipients/Certificates/ca.crt /usr/local/share/ca-certificates/ca.crt diff --git a/Source/Dockerfile.get-data-recipients.integration-tests b/Source/Dockerfile.get-data-recipients.integration-tests index 357613c..c15d293 100644 --- a/Source/Dockerfile.get-data-recipients.integration-tests +++ b/Source/Dockerfile.get-data-recipients.integration-tests @@ -1,6 +1,6 @@ # Dockerfile for running GetDataRecipient integration tests -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src # EXPOSE 9999 # EXPOSE 9998 diff --git a/Source/Dockerfile.integration-tests b/Source/Dockerfile.integration-tests index c22b467..2e80e7e 100644 --- a/Source/Dockerfile.integration-tests +++ b/Source/Dockerfile.integration-tests @@ -1,6 +1,6 @@ # Dockerfile for running integration tests -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src EXPOSE 9999 EXPOSE 9998 diff --git a/Source/Dockerfile.standalone b/Source/Dockerfile.standalone index 3aa782b..ecef039 100644 --- a/Source/Dockerfile.standalone +++ b/Source/Dockerfile.standalone @@ -4,7 +4,7 @@ ############################################################################### # Build base layer ############################################################################### -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base # Install nodejs, npm and live-server, which are needed by the auth UI RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -13,6 +13,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ nginx \ && rm -rf /var/lib/apt/lists/* +# install now so it will be immediately available for supervisord +RUN npm install -g react-inject-env + WORKDIR /app EXPOSE 8080 EXPOSE 8001 @@ -40,10 +43,15 @@ RUN npm run build COPY CdrAuthServer.UI/nginx/nginx_auth_ui.conf /etc/nginx/conf.d/default.conf COPY CdrAuthServer.UI/nginx/nginx.gzip.conf /etc/nginx/conf.d/gzip.conf +# Copy nginx SSL certificates to container. +RUN mkdir -p /etc/nginx/ssl +COPY CdrAuthServer.UI/nginx/ssl/authserver-ui.crt /etc/nginx/ssl/authserver-ui.crt +COPY CdrAuthServer.UI/nginx/ssl/authserver-ui.key /etc/nginx/ssl/authserver-ui.key + ############################################################################### # Build CdrAuthServer API layer ############################################################################### -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src COPY ./ . @@ -75,6 +83,8 @@ COPY --from=ui-build /app/build /usr/share/nginx/html/ui COPY --from=ui-build /app/build /usr/share/nginx/html/ui COPY --from=ui-build /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf COPY --from=ui-build /etc/nginx/conf.d/gzip.conf /etc/nginx/conf.d/gzip.conf +COPY --from=ui-build /etc/nginx/ssl/authserver-ui.crt /etc/nginx/ssl/authserver-ui.crt +COPY --from=ui-build /etc/nginx/ssl/authserver-ui.key /etc/nginx/ssl/authserver-ui.key @@ -92,25 +102,18 @@ USER 0 RUN setcap cap_net_bind_service=+ep /usr/sbin/nginx # Run as non-root user -RUN addgroup --group appgroup --gid 2000 -RUN adduser --uid 1000 --gid 2000 "appuser" -RUN chown -R appuser:appgroup /app -RUN chown -R appuser:appgroup /usr/bin -RUN chown -R appuser:appgroup /usr/local -RUN chown -R appuser:appgroup /tmp -RUN chown -R appuser:appgroup /var/log/nginx -RUN chown -R appuser:appgroup /var/lib/nginx - -RUN touch /run/nginx.pid \ - && chown -R appuser:appgroup /run/nginx.pid -RUN touch /usr/share/nginx/html/ui/env.js \ - && chown -R appuser:appgroup /usr/share/nginx/html/ui/env.js - - -USER appuser:appgroup +RUN chown -R app:app /app \ +&& chown -R app:app /var/log/nginx \ +&& chown -R app:app /var/lib/nginx \ +&& touch /run/nginx.pid \ +&& chown -R app:app /run/nginx.pid \ +&& touch /usr/share/nginx/html/ui/env.js \ +&& chown -R app:app /usr/share/nginx/html/ui/env.js +  +USER app ENV ASPNETCORE_URLS=https://+:8001;http://+:8080 # Entry point ################################################################# -ENTRYPOINT ["/usr/bin/supervisord", "-c", "/app/supervisord.standalone.conf", "-u", "1000"] -# ENTRYPOINT ["tail", "-f", "/dev/null"] +ENTRYPOINT ["/usr/bin/supervisord", "-c", "/app/supervisord.standalone.conf"] +# ENTRYPOINT ["tail", "-f", "/dev/null"] \ No newline at end of file diff --git a/Source/Dockerfile.unit-tests b/Source/Dockerfile.unit-tests index a3a6242..83c4749 100644 --- a/Source/Dockerfile.unit-tests +++ b/Source/Dockerfile.unit-tests @@ -1,6 +1,6 @@ # Dockerfile for running unit tests -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src # Default ASPNETCORE_ENVIRONMENT to Release @@ -23,8 +23,8 @@ ARG FEED_URI ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS="{\"endpointCredentials\": [{\"endpoint\":\"${FEED_URI}\", \"username\":\"docker\", \"password\":\"${FEED_ACCESSTOKEN}\"}]}" RUN echo $VSS_NUGET_EXTERNAL_FEED_ENDPOINTS -RUN dotnet restore CdrAuthServer.sln -RUN dotnet build CdrAuthServer.sln --configuration Release +RUN dotnet restore CdrAuthServer.slnx +RUN dotnet build CdrAuthServer.slnx --configuration Release # Run tests -ENTRYPOINT ["dotnet", "test", "CdrAuthServer.sln", "--configuration", "Release", "--filter", "UnitTests", "--no-build", "--logger", "trx;verbosity=detailed", "--results-directory", "/testresults"] \ No newline at end of file +ENTRYPOINT ["dotnet", "test", "CdrAuthServer.slnx", "--configuration", "Release", "--filter", "UnitTests", "--no-build", "--logger", "trx;verbosity=detailed", "--results-directory", "/testresults"] \ No newline at end of file diff --git a/Source/supervisord.standalone.conf b/Source/supervisord.standalone.conf index 0700196..5e3ccc0 100644 --- a/Source/supervisord.standalone.conf +++ b/Source/supervisord.standalone.conf @@ -10,21 +10,12 @@ stdout_logfile_maxbytes=0 directory=/app/cdrauthserver command=/usr/bin/dotnet /app/cdrauthserver/CdrAuthServer.dll -[program:CdrAuthServer-UI-InjectReactEnvironment] -priority=1 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -directory=/usr/share/nginx/html/ui -command=npx --yes react-inject-env set -d /usr/share/nginx/html/ui -autorestart=false -startsecs=0 - [program:CdrAuthServer-UI] priority=5 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 directory=/usr/share/nginx/html/ui -command=nginx -g "daemon off;" +command=bash -c "react-inject-env set -d /usr/share/nginx/html/ui && exec nginx -g 'daemon off;'" autostart=true autorestart=true startretries=5