diff --git a/.azuredevops/pipelines/build-v2.yml b/.azuredevops/pipelines/build-v2.yml new file mode 100644 index 0000000..c6b221e --- /dev/null +++ b/.azuredevops/pipelines/build-v2.yml @@ -0,0 +1,254 @@ +# Build pipeline v2 (Containerised) + +resources: + repositories: + - repository: MockRegister + type: git + name: sb-mock-register + ref: develop + - repository: MockDataHolder + type: git + name: sb-mock-data-holder + ref: develop + - repository: MockDataHolder-Energy + type: git + name: sb-mock-data-holder-energy + ref: develop + +trigger: + - develop + +pool: + vmImage: ubuntu-latest + +steps: + +# Checkout repositories +- checkout: MockRegister +- checkout: MockDataHolder +- checkout: MockDataHolder-Energy +- checkout: self + +# Build mock-register +- task: Docker@2 + displayName: Build mock-register image + inputs: + command: build + Dockerfile: $(Build.SourcesDirectory)/sb-mock-register/Source/Dockerfile + buildContext: $(Build.SourcesDirectory)/sb-mock-register/Source + repository: mock-register + tags: latest + +# Build mock-data-holder +- task: Docker@2 + displayName: Build mock-data-holder image + inputs: + command: build + Dockerfile: $(Build.SourcesDirectory)/sb-mock-data-holder/Source/Dockerfile + buildContext: $(Build.SourcesDirectory)/sb-mock-data-holder/Source + repository: mock-data-holder + tags: latest + +# Build mock-data-holder-energy +- task: Docker@2 + displayName: Build mock-data-holder-energy image + inputs: + command: build + Dockerfile: $(Build.SourcesDirectory)/sb-mock-data-holder-energy/Source/Dockerfile + buildContext: $(Build.SourcesDirectory)/sb-mock-data-holder-energy/Source + repository: mock-data-holder-energy + tags: latest + +# Build mock-data-recipient +- task: Docker@2 + displayName: Build mock-data-recipient image + inputs: + command: build + Dockerfile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/Dockerfile + buildContext: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source + repository: mock-data-recipient + tags: latest + +# Build mock-data-recipient-unit-tests +- task: Docker@2 + displayName: Build mock-data-recipient-unit-tests image + inputs: + command: build + Dockerfile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/Dockerfile.unit-tests + buildContext: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source + repository: mock-data-recipient-unit-tests + tags: latest + +# Build mock-data-recipient-integration-tests +- task: Docker@2 + displayName: Build mock-data-recipient-integration-tests image + inputs: + command: build + Dockerfile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/Dockerfile.integration-tests + buildContext: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source + repository: mock-data-recipient-integration-tests + tags: latest + +# Build mock-data-recipient-e2e-tests +- task: Docker@2 + displayName: Build mock-data-recipient-e2e-tests image + inputs: + command: build + Dockerfile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/Dockerfile.e2e-tests + buildContext: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source + repository: mock-data-recipient-e2e-tests + tags: latest + +# List docker images +- task: Docker@2 + displayName: List Docker images + condition: always() + inputs: + command: images + +# Run unit tests +- task: DockerCompose@0 + displayName: Unit tests - Up + inputs: + action: Run a Docker Compose command + dockerComposeFile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/docker-compose.UnitTests.yml + dockerComposeCommand: up --abort-on-container-exit --exit-code-from mock-data-recipient-unit-tests + +# Remove unit tests +- task: DockerCompose@0 + displayName: Unit tests - Down + condition: always() + inputs: + action: Run a Docker Compose command + dockerComposeFile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/docker-compose.UnitTests.yml + dockerComposeCommand: down + +# Run integration tests +- task: DockerCompose@0 + displayName: Integration tests - Up + condition: always() + inputs: + action: Run a Docker Compose command + dockerComposeFile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/docker-compose.IntegrationTests.yml + dockerComposeCommand: up --abort-on-container-exit --exit-code-from mock-data-recipient-integration-tests + +# Remove integration tests +- task: DockerCompose@0 + displayName: Integration tests - Down + condition: always() + inputs: + action: Run a Docker Compose command + dockerComposeFile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/docker-compose.IntegrationTests.yml + dockerComposeCommand: down + +# Run e2e tests +- task: DockerCompose@0 + displayName: E2E tests - Up + condition: always() + inputs: + action: Run a Docker Compose command + dockerComposeFile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/docker-compose.E2ETests.yml + dockerComposeCommand: up --abort-on-container-exit --exit-code-from mock-data-recipient-e2e-tests + +# Remove e2e tests +- task: DockerCompose@0 + displayName: E2E tests - Down + condition: always() + inputs: + action: Run a Docker Compose command + dockerComposeFile: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/docker-compose.E2ETests.yml + dockerComposeCommand: down + +# Save docker image to TAR so it can be published +- task: Docker@2 + displayName: Save MockDataRecipient image to TAR + # condition: always() + inputs: + repository: mock-data-recipient + command: save + arguments: --output $(build.artifactstagingdirectory)/mock-data-recipient.image.tar mock-data-recipient + addPipelineData: false + +# Publish docker image +- task: PublishPipelineArtifact@1 + displayName: Publish container images + # condition: always() + inputs: + path: $(build.artifactstagingdirectory) + artifact: Container Images + +# Publish mock-register logs +- publish: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/_temp/mock-register/tmp + displayName: Publish MockRegister logs + condition: always() + artifact: Mock-Register - Logs + +# Publish mock-data-holder logs +- publish: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/_temp/mock-data-holder/tmp + displayName: Publish MockDataHolder logs + condition: always() + artifact: Mock-Data-Holder - Logs + +# Publish mock-data-holder-energy logs +- publish: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/_temp/mock-data-holder-energy/tmp + displayName: Publish MockDataHolder-Energy logs + condition: always() + artifact: Mock-Data-Holder-Energy - Logs + +# Publish mock-data-recipient logs +- publish: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/_temp/mock-data-recipient/tmp + displayName: Publish MockDataRecipient logs + condition: always() + artifact: Mock-Data-Recipient - Logs + +# Publish mock-data-recipient unit tests results +- publish: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/_temp/mock-data-recipient-unit-tests/testresults + displayName: Publish unit tests + condition: always() + artifact: Mock-Data-Recipient - Unit tests + +# Publish mock-data-recipient integration tests results +- publish: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/_temp/mock-data-recipient-integration-tests/testresults + displayName: Publish integration tests + condition: always() + artifact: Mock-Data-Recipient - Integration tests + +# Publish mock-data-recipient e2e tests results +- publish: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/_temp/mock-data-recipient-e2e-tests/testresults + displayName: Publish e2e tests + condition: always() + artifact: Mock-Data-Recipient - E2E tests + +# TODO - MJS - Run formatter over TRX to produce formatted report suitable for attaching to Devops US & publish as artifact + +- task: UseDotNet@2 + displayName: 'Use .NET 6 sdk' + condition: always() + inputs: + packageType: sdk + version: '6.0.x' + performMultiLevelLookup: true + +- task: CmdLine@2 + displayName: 'Install dotnet-ef' + condition: always() + inputs: + script: 'dotnet tool install --global dotnet-ef' + +- task: CmdLine@2 + displayName: 'Check dotnet-ef version' + condition: always() + inputs: + script: 'dotnet-ef' + +- script: | + cd $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/CDR.DataRecipient.Repository.SQL + dotnet ef migrations bundle --context RecipientDatabaseContext --verbose --self-contained + ls + displayName: 'Run EF Migrations bundle' + condition: always() + +- publish: $(Build.SourcesDirectory)/sb-mock-data-recipient/Source/CDR.DataRecipient.Repository.SQL/efbundle + displayName: Publish EF Migration bundle + condition: always() + artifact: Database Migration Scripts diff --git a/.azuredevops/pipelines/dotnet.yml b/.azuredevops/pipelines/dotnet.yml index 82fc43f..fe91fff 100644 --- a/.azuredevops/pipelines/dotnet.yml +++ b/.azuredevops/pipelines/dotnet.yml @@ -109,7 +109,7 @@ steps: del /Q mdr.db # Start APIs -- template: Pipeline/start-apis.yml +- template: templates/start-apis.yml # Run integration tests - task: VSTest@2 diff --git a/.azuredevops/pull_request_template.md b/.azuredevops/pull_request_template.md index 7371e3e..0c8d12c 100644 --- a/.azuredevops/pull_request_template.md +++ b/.azuredevops/pull_request_template.md @@ -1,8 +1,12 @@ **Checklist:** (Put an `x` in all the boxes that apply) - [ ] My code follows the code style of this project. +- [ ] I have set this Pull Request to Auto Complete with the delete source branch option selected. +- [ ] Commented out code has been removed or will be removed. - [ ] I have updated the documentation accordingly. - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. +- [ ] I have updated the `CHANGELOG.md` file as appropriate. + **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...) @@ -21,4 +25,3 @@ **Other information**: - diff --git a/.github/stale.yml b/.github/stale.yml index 5919551..4524e42 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -8,6 +8,7 @@ exemptLabels: - security - investigating - bug report + - backlog # Label to use when marking an issue as stale staleLabel: wontfix # Comment to post when marking an issue as stale. Set to `false` to disable diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d195f79..86da43d 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -28,15 +28,15 @@ on: env: buildConfiguration: 'Release' buildRuntime: 'win-x64' - runEnvironment: 'Pipeline' - ASPNETCORE_ENVIRONMENT: 'Pipeline' + runEnvironment: 'Release' + ASPNETCORE_ENVIRONMENT: 'Release' jobs: build-and-test: - runs-on: windows-latest - - ## NOTE: This workflow needs to also checkout the Mock Register, and Mock Data Holder for testing. - ## This workflow will checkout the ConsumerDataRight/mock-register and ConsumerDataRight/mock-data-holder projects + runs-on: ubuntu-latest + + ## NOTE: This workflow needs to also checkout the Mock Register for testing. + ## This workflow will checkout the ConsumerDataRight/mock-register project steps: - name: Checkout Data Recipient @@ -44,197 +44,102 @@ jobs: with: path: ./mock-data-recipient - - name: Checkout Register (Main Branch) - uses: actions/checkout@v2 + - name: Pull Mock Register Image (main) if: ${{ github.ref == 'refs/heads/main' }} - with: - repository: ConsumerDataRight/mock-register - ref: main - path: ./mock-register + run: | + docker pull consumerdataright/mock-register:main + docker image tag consumerdataright/mock-register:main mock-register:latest - - name: Checkout Register (Develop Branch) - uses: actions/checkout@v2 + - name: Pull Mock Register Image (develop) if: ${{ github.ref != 'refs/heads/main' }} - with: - repository: ConsumerDataRight/mock-register - ref: develop - path: ./mock-register + run: | + docker pull consumerdataright/mock-register:develop + docker image tag consumerdataright/mock-register:develop mock-register:latest - - name: Checkout Data Holder (Main Branch) - uses: actions/checkout@v2 + - name: Pull Mock Data Holder Image (main) if: ${{ github.ref == 'refs/heads/main' }} - with: - repository: ConsumerDataRight/mock-data-holder - ref: main - path: ./mock-data-holder + run: | + docker pull consumerdataright/mock-data-holder:main + docker image tag consumerdataright/mock-data-holder:main mock-data-holder:latest - - name: Checkout Data Holder (Develop Branch) - uses: actions/checkout@v2 + - name: Pull Mock Data Holder Image (develop) if: ${{ github.ref != 'refs/heads/main' }} - with: - repository: ConsumerDataRight/mock-data-holder - ref: develop - path: ./mock-data-holder - - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.x - - - name: Restore dependencies run: | - dotnet restore ${{ github.workspace }}\mock-data-recipient\Source\DataRecipient.sln - dotnet restore ${{ github.workspace }}\mock-data-holder\Source\DataHolder.sln - dotnet restore ${{ github.workspace }}\mock-register\Source\Register.sln - - - name: Build + docker pull consumerdataright/mock-data-holder:develop + docker image tag consumerdataright/mock-data-holder:develop mock-data-holder:latest + + - name: Pull Mock Data Holder Energy Image (main) + if: ${{ github.ref == 'refs/heads/main' }} run: | - dotnet build ${{ github.workspace }}\mock-data-recipient\Source\DataRecipient.sln --configuration ${{ env.buildConfiguration }} - dotnet build ${{ github.workspace }}\mock-data-holder\Source\DataHolder.sln --configuration ${{ env.buildConfiguration }} - dotnet build ${{ github.workspace }}\mock-register\Source\Register.sln --configuration ${{ env.buildConfiguration }} - - - name: Patch Register Seed Data + docker pull consumerdataright/mock-data-holder-energy:main + docker image tag consumerdataright/mock-data-holder-energy:main mock-data-holder-energy:latest + + - name: Pull Mock Data Holder Energy Image (develop) + if: ${{ github.ref != 'refs/heads/main' }} run: | - Write-Host "Overwriting seed-data.json for the Register with a version that has been patched to use the MDR endpoints." - Copy-Item -Path "${{ github.workspace }}\mock-data-recipient\Source\CDR.DataRecipient.IntegrationTests\ForPipeline\seed-data.json" -Destination "${{ github.workspace }}\mock-register\Source\CDR.Register.Admin.API\Data" -Force - Get-Content "${{ github.workspace }}\mock-register\Source\CDR.Register.Admin.API\Data\seed-data.json" - shell: powershell + docker pull consumerdataright/mock-data-holder-energy:develop + docker image tag consumerdataright/mock-data-holder-energy:develop mock-data-holder-energy:latest - - name: Create CDR folder + - name: List contents + if: always() run: | - echo ${{ github.workspace }} - - Write-Host "Creating the temporary CDR directory which holds the logs and database file..." - New-Item -ItemType Directory -Path ${{ github.workspace }}\cdr -Force - shell: powershell + ls + cd mock-data-recipient + ls + cd .. - - name: Set AEST timezone + # Build mock-data-recipient image + - name: Build the mock-data-recipient image run: | - cd ${{ github.workspace }} - tzutil /s "AUS Eastern Standard Time" - shell: powershell + docker build ./mock-data-recipient/Source --file ./mock-data-recipient/Source/Dockerfile --tag mock-data-recipient:latest - - name: Install certificates + # Build mock-data-recipient-integration-tests image + - name: Build the mock-data-recipient-integration-tests image run: | - $PlainPassword = "#M0ckCDRCA#" - $SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force - Import-PfxCertificate -Password $SecurePassword -FilePath "mock-data-holder/CertificateManagement/mtls/ca.pfx" -CertStoreLocation Cert:\LocalMachine\Root + docker build ./mock-data-recipient/Source --file ./mock-data-recipient/Source/Dockerfile.integration-tests --tag mock-data-recipient-integration-tests:latest - $PlainPassword = "#M0ckDataHolder#" - $SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force - Import-PfxCertificate -Password $SecurePassword -FilePath "mock-data-holder/CertificateManagement/tls/mock-data-holder.pfx" -CertStoreLocation Cert:\LocalMachine\Root - shell: powershell + # Run integration tests + - name: Run integration tests + run: | + docker-compose -f './mock-data-recipient/Source/docker-compose.IntegrationTests.yml' up --abort-on-container-exit --exit-code-from mock-data-recipient-integration-tests - - name: Unit Tests + # Remove integration tests + - name: Remove integration tests run: | - ($env:ASPNETCORE_ENVIRONMENT="${{ env.runEnvironment }}") | dotnet test ${{ github.workspace }}\mock-data-recipient\Source\CDR.DataRecipient.Repository.SQLite.UnitTests\bin\Release\net5.0\CDR.DataRecipient.Repository.SQLite.UnitTests.dll --logger "trx;verbosity=detailed;logfilename=repository-sqlite.trx" --results-directory ${{ github.workspace }}\cdr\test-results + docker-compose -f './mock-data-recipient/Source/docker-compose.IntegrationTests.yml' down - - name: Archive Unit Test results - uses: actions/upload-artifact@v2 - if: always() - with: - name: unit-test-results - path: ${{ github.workspace }}\cdr\test-results + # List docker images + - name: List Docker images + run: | + docker images - - name: Archive Unit Test logs/dbs - uses: actions/upload-artifact@v2 - if: always() - with: - name: unit-test-artifacts - path: | - ${{ github.workspace }}\cdr\Logs - ${{ github.workspace }}\cdr\*.db + # Build mock-data-recipient-e2e-tests image + - name: Build the mock-data-recipient-e2e-tests image + run: | + docker build ./mock-data-recipient/Source --file ./mock-data-recipient/Source/Dockerfile.e2e-tests --tag mock-data-recipient-e2e-tests:latest - - name: Delete Unit Test Data + # Run e2e tests + - name: Run e2e tests run: | - cd ${{ github.workspace }}\cdr - Remove-Item -Path ${{ github.workspace }}\cdr\* -Recurse -Force - shell: powershell + docker-compose -f './mock-data-recipient/Source/docker-compose.E2ETests.yml' up --abort-on-container-exit --exit-code-from mock-data-recipient-e2e-tests - - name: Integration Tests + # Remove e2e tests + - name: Remove e2e tests run: | - echo ${{ github.workspace }} - - Write-Host "Fix appsettings.Pipeline.json file paths for MDR..." - ((Get-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.API.Gateway.TLS\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-register', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.API.Gateway.TLS\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.API.Gateway.mTLS\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-register', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.API.Gateway.mTLS\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.Admin.API\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-register', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.Admin.API\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.Discovery.API\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-register', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.Discovery.API\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.SSA.API\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-register', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.SSA.API\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.Status.API\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-register', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.Status.API\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.IdentityServer\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-register', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-register\Source\CDR.Register.IdentityServer\appsettings.${{ env.runEnvironment }}.json - - ((Get-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Manage.API\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-data-holder', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Manage.API\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Resource.API\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-data-holder', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Resource.API\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Public.API\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-data-holder', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Public.API\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.IdentityServer\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-data-holder', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.IdentityServer\appsettings.${{ env.runEnvironment }}.json - ((Get-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.API.Gateway.mTLS\appsettings.${{ env.runEnvironment }}.json -Raw) -replace 'mock-data-holder', 'mock-data-recipient') | Set-Content -Path ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.API.Gateway.mTLS\appsettings.${{ env.runEnvironment }}.json - - Write-Host "Running the register..." - cd ${{ github.workspace }}\mock-register\Source\CDR.Register.API.Gateway.TLS - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --launch-profile CDR.Register.API.Gateway.TLS.${{ env.runEnvironment }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-register\Source\CDR.Register.API.Gateway.mTLS - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --launch-profile CDR.Register.API.Gateway.mTLS.${{ env.runEnvironment }} --no-build --no-restore" + docker-compose -f './mock-data-recipient/Source/docker-compose.E2ETests.yml' down - cd ${{ github.workspace }}\mock-register\Source\CDR.Register.Admin.API - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --launch-profile CDR.Register.Admin.API.${{ env.runEnvironment }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-register\Source\CDR.Register.Discovery.API - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --launch-profile CDR.Register.Discovery.API.${{ env.runEnvironment }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-register\Source\CDR.Register.SSA.API - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --launch-profile CDR.Register.SSA.API.${{ env.runEnvironment }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-register\Source\CDR.Register.Status.API - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --launch-profile CDR.Register.Status.API.${{ env.runEnvironment }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-register\Source\CDR.Register.IdentityServer - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --launch-profile CDR.Register.IdentityServer.${{ env.runEnvironment }} --no-build --no-restore" + # Build mock-data-recipient-unit-tests image + - name: Build the mock-data-recipient-unit-tests image + run: | + docker build ./mock-data-recipient/Source --file ./mock-data-recipient/Source/Dockerfile.unit-tests --tag mock-data-recipient-unit-tests:latest - Write-Host "Running the data holder..." - cd ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Manage.API - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Resource.API - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.Public.API - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.IdentityServer - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --no-build --no-restore" - - cd ${{ github.workspace }}\mock-data-holder\Source\CDR.DataHolder.API.Gateway.mTLS - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --no-build --no-restore" - - Write-Host "Running the data recipient..." - cd ${{ github.workspace }}\mock-data-recipient\Source\CDR.DataRecipient.Web - Start-Process dotnet -ArgumentList "run -v m -c ${{ env.buildConfiguration }} --launch-profile CDR.DataRecipient.Web.${{ env.runEnvironment }}" - - Write-Host "Sleeping for 30 seconds to allow solutions to startup..." - Start-Sleep -s 30 - - Write-Host "Listing contents of ${{ github.workspace }}\cdr directory..." - Get-ChildItem ${{ github.workspace }}\cdr - - Write-Host "Running the integration tests..." - cd ${{ github.workspace }}\mock-data-recipient\Source\CDR.DataRecipient.IntegrationTests - ($env:ASPNETCORE_ENVIRONMENT="${{ env.runEnvironment }}") | dotnet test ${{ github.workspace }}\mock-data-recipient\Source\CDR.DataRecipient.IntegrationTests\bin\Release\net5.0\CDR.DataRecipient.IntegrationTests.dll --settings ${{ github.workspace }}\mock-data-recipient\Source\CDR.DataRecipient.IntegrationTests\integration.runsettings --logger "trx;verbosity=detailed;logfilename=mdr-integration.trx" --results-directory ${{ github.workspace }}\cdr\test-results - shell: powershell + # Run unit tests + - name: Run unit tests + run: | + docker-compose -f './mock-data-recipient/Source/docker-compose.UnitTests.yml' up --abort-on-container-exit --exit-code-from mock-data-recipient-unit-tests - - name: Archive integration test results - uses: actions/upload-artifact@v2 - if: always() - with: - name: integration-test-results - path: ${{ github.workspace }}\cdr\test-results + # Remove unit tests + - name: Remove unit tests + run: | + docker-compose -f './mock-data-recipient/Source/docker-compose.UnitTests.yml' down - - name: Archive integration test logs/dbs - uses: actions/upload-artifact@v2 - if: always() - with: - name: integration-test-artifacts - path: | - ${{ github.workspace }}\cdr\Logs - ${{ github.workspace }}\cdr\*.db diff --git a/.gitignore b/.gitignore index 0595daf..65e4aae 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +# temp folders +**/_temp/ + # VS Code **/.vscode/ @@ -55,7 +58,6 @@ BenchmarkDotNet.Artifacts/ project.lock.json project.fragment.lock.json artifacts/ -**/Properties/launchSettings.json # StyleCop StyleCopReport.xml @@ -331,3 +333,8 @@ ASALocalRun/ # MFractors (Xamarin productivity tool) working folder .mfractor/ + +Source/CDR.DataRecipient.Web/_healthcheck_ready + +# Sonarqube +.sonarqube diff --git a/CHANGELOG.md b/CHANGELOG.md index f57e507..fc461cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,17 +6,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.2.0] - 2022-05-25 +### Added +- PKCE support added to "Consent and Authorisations" and "PAR" in preparation for FAPI 1.0. +- Ability to connect and authenticate with data holders that have implemented either FAPI 1.0 Migration Phase 1 and Phase 2. +- Ability to connect to and test the [Mock Data Holder Energy](https://github.com/ConsumerDataRight/mock-data-holder-energy) and other Energy Data Holders. + +### Changed +- Upgraded the Mock Data Recipient codebase to .NET 6. +- Replaced SQLite database with MSSQL database. +- Changed the TLS certificates for the mock data recipient to be signed by the Mock CDR CA. +- Extra steps detailed for using the solution in visual studio, docker containers and docker compose file. +- Use the latest endpoints from the [Mock Register](https://github.com/ConsumerDataRight/mock-register) that support Banking, Energy and Telco as an industry. +- Quality of Life updates to assist with usability and testing. +- Regenerated all certificates to allow for another year before they expire. + ## [0.1.2] - 2022-05-09 ### Fixed - Banking API swagger in data sharing not displaying. [Issue 30](https://github.com/ConsumerDataRight/mock-data-recipient/issues/30) ## [0.1.1] - 2021-12-07 ### Added -- GitHub Actions Workflow for Build, Unit Test, and Integration Test project. -- GitHub Issue config with supporting links to CDR related information. +- GitHub Actions Workflow for Build, Unit Test, and Integration Test project. +- GitHub Issue config with supporting links to CDR related information. ### Changed -- Minor changes to pipeline appsettings files to support GitHub Actions. +- Minor changes to pipeline appsettings files to support GitHub Actions. - Minor changes to docker command in the ReadMe. [Issue 25](https://github.com/ConsumerDataRight/mock-data-holder/issues/25) ### Fixed @@ -25,4 +40,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.1.0] - 2021-10-01 ### Added -- First release of the Mock Data Recipient. +- First release of the Mock Data Recipient. \ No newline at end of file diff --git a/CertificateManagement/README.md b/CertificateManagement/README.md index 019e008..9bdc381 100644 --- a/CertificateManagement/README.md +++ b/CertificateManagement/README.md @@ -27,7 +27,7 @@ Consult the [CertificateManagement](https://github.com/ConsumerDataRight/mock-re Endpoints that are not protected by mTLS are protected by TLS. The server certificate used for TLS communication can be provisioned by the CDR CA, or alternatively participants can used a trusted third party CA. -For the Mock Data Recipient, a self-signed TLS certificate is used. The self-signed certificate will not use the Mock CDR CA, like the mTLS certificates do. +For the Mock Data Recipient, a self-signed TLS certificate is used. The self-signed certificate is issued by the Mock CDR CA, like the mTLS certificates are. The TLS certificate for the Mock Data Recipient is available at `tls\mock-data-recipient.pfx` and has the password of `#M0ckDataRecipient#`. diff --git a/CertificateManagement/jwks/jwks.csr b/CertificateManagement/jwks/jwks.csr index 2a4c54c..39c9b41 100644 --- a/CertificateManagement/jwks/jwks.csr +++ b/CertificateManagement/jwks/jwks.csr @@ -2,18 +2,18 @@ MIIDFzCCAf8CAQAwazEeMBwGA1UEAwwVTW9ja0RhdGFSZWNpcGllbnRKd2tzMQsw CQYDVQQGEwJBVTEMMAoGA1UECAwDQUNUMREwDwYDVQQHDAhDYW5iZXJyYTENMAsG A1UECgwEQUNDQzEMMAoGA1UECwwDQ0RSMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEA0Iv8ocA0NvV7dd9hHI+n21OuRD+9bnLw213Y3q7VFwg2tufu0Z8T -POoHDjWVkbxaq1K8nPDtBAdR5HXnbjXFxPGwRV8UgGMDSI6Z/M0j1bUGV9D9rukc -vJ8Z7QpDbKuZzeIg6LrXfIpvyNisEXjMJI14zz9dX1EtWUYQTRq5r2UF8C8pHE1y -UtaVnsOZBLmLqMPOPNG1JsK2WhL1uOa0ef+UTQSjN1fw5D2d9K8azUPQL2ecsJA/ -ZTDZovVzS0fP0MdRXZ/uNRmaww2zg0tIJLQH1Z7AmwAP4LrPIGma6nWo6+57ZJ26 -3k84o9fdR5+hVIcQDEGlKpZDoeNLOBg09wIDAQABoGcwZQYJKoZIhvcNAQkOMVgw +MIIBCgKCAQEAwsfaGZ/bVTgF8tl8oy79iVmLZ/nCdAiz5cptwP69qRQB+K0J6DNi +AB3DOZ+rlgPZHtWwVGTNvvVE48uY6zWvghj2M7FpxjjqVHCoL98mh5ZLAToucQT3 +MfVJ62laS4iy6nLnAh9RdUqIrdT4Pji8BajFva1TWWBRYpHPykDuv2ZClRglScrm +uIlVOXwDWNCXvIGE4qGwEX2m3UGYFPEv3dkBinJxcsbmEfNcWnjneoyWemcw9x55 +d+3DxwpLKfjUEu0uxChYTDVk9Ii3uzZls9qHVBwOtrT6c9AKJmtC/slqMtaqxvgB +ETI8tH8Jl3+5jNoQg094xLdzXftHc06dswIDAQABoGcwZQYJKoZIhvcNAQkOMVgw VjAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSUBAf8EDDAKBggrBgEF BQcDATAhBgNVHREEGjAYghZtb2NrZGF0YXJlY2lwaWVudC5qd2tzMA0GCSqGSIb3 -DQEBCwUAA4IBAQBbJRUyrnXH6Hl5UKok/tbOkOtRKH2NTtDeT6i4a+GTeziNyi41 -ObCHk6YqJ780vqw735Yi9KULAbOqnEMd6sfbJeOGl3evveSX0zPVHXQw5d7n8dpX -N3oMF2qq/ygPfJ0/1uLwRyTlhAHEL2WPKmwy88zBYtbx/10KaslxHiTbaVX0eZCz -+umUTsk7tUBb0kGFlWrBnP9gHIDFje+1zMBOKL4OykB4/Mdt7mHINYzUxUytq4c2 -7QVPNt6a8RIpUKpeO+Ao9b3YHZnwANoWc5SXRLSZE5U72DEHjHULzv5Mj8Qyf7U8 -cNjJgI120tbBvbSWrpSQxkr6yDUZMwYsBS84 +DQEBCwUAA4IBAQA9VPRKhIzKZBaf7pIAeopUi89w4+dXXTF1omVYBaRABPCylLJd +hHcPnQPODXMCy7dMtEa71LrwWKa/ueMEXSkhXp/3xgWLAxOSbuFsBQITlFsyi7cK +K+2TMQwQdCuCKx8ikTTbMJIYCKRKRWqeh2dtajE4j7V+D/uJtmx8ibwFW+ac/d7v +sJnzxgm6RDbZgVjNVb+jzO6Gxy3q4Y+ES5+Piwt+MO9xUp8PMpxxpuHc5Dp9pSlo +04qJG5q2cJMzCfpwCLPdViyJIbJHAI0aaHq0UJrxZxmqgogxCWzo+HkbashZ7EgO +tvoq14yIQI3p8ap3WhUFCZJAves0jNLaZYDi -----END CERTIFICATE REQUEST----- diff --git a/CertificateManagement/jwks/jwks.key b/CertificateManagement/jwks/jwks.key index b355938..b9157c0 100644 --- a/CertificateManagement/jwks/jwks.key +++ b/CertificateManagement/jwks/jwks.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQi/yhwDQ29Xt1 -32Ecj6fbU65EP71ucvDbXdjertUXCDa25+7RnxM86gcONZWRvFqrUryc8O0EB1Hk -deduNcXE8bBFXxSAYwNIjpn8zSPVtQZX0P2u6Ry8nxntCkNsq5nN4iDoutd8im/I -2KwReMwkjXjPP11fUS1ZRhBNGrmvZQXwLykcTXJS1pWew5kEuYuow8480bUmwrZa -EvW45rR5/5RNBKM3V/DkPZ30rxrNQ9AvZ5ywkD9lMNmi9XNLR8/Qx1Fdn+41GZrD -DbODS0gktAfVnsCbAA/gus8gaZrqdajr7ntknbreTzij191Hn6FUhxAMQaUqlkOh -40s4GDT3AgMBAAECggEATfcXwoztuGI7/sw9LQVT1r5JF0DRHBqiixBhxJaOGac7 -dVPuR7X15j8D1j8YJLzLFOPAmdfEdE4cQpIFrIEz57YHlVe/fWQG1Thiv00eCYY8 -0dXTEXIbCTVd5u2AWX8p5/uTHA7GAsxqkCbY5UtI3p15PdnNmZXqo0Z7T6gfJT+s -vit0S2/ZZgNB6T/o6iEkVrSsYlRRhNKKBRbpv2iQt8INaYSooT78j6L4Yi0Vi/vX -ZW/1x5cpQFd2cgs9cQ7/pR0Av41qFmUt6Y6XFtuwNjMVO3P9EiFT0LLEv+IZ6l3C -Iqe5JIcY9z87sM0Gt2k8oC4+eSIxawg+rIiOK3RjUQKBgQD/fkKVebeVdfBFBPbY -bC0BXQIsO9yV6hcnkp8ijujCi4rUkBNZBnCpkxMs+0wzbVvo9Kmv25RXZJqtRwe1 -vf1U/kezNU+9f1CQ+s3bfbaRB0iY8aqORcbtRfIPz3ZGmXdTX559AgsAgRzxGJL7 -+cemBtccfLpWi3qt/zqtwATzOQKBgQDQ9eMlslHFcE0OZ2Xab0wpayTJ5XMXY38R -xsjQqdj/ZXJSuOtKcVqnTSiPc3kJZ6Tp4Wct0POUlhO5rlGc8wYeNIJ2FNs49Lws -PorrnlyrJF1oHTsFmfXGH8xxAgi9lKa6b1xrTFNfjVSv7LnF6fIPlGo4rIQtXzKN -smGey8B5rwKBgQDeih99CzP5H21U8OoBwNfCpDzMQqf0fJ4GfhPWihv7uIgIdiYk -GRPw4IaHW6wX711rIBDdeKlRJfQEkiYJC5+pdIMHeZwnNsn6Pjsov+tRj8KQVY91 -tRl8erxJQS+IdwwUtujZgfoLSmrnJbyBdiOMXdDoo0u7LmqBPBrkVKj7IQKBgQCE -KfFoR1fW5Aeow5c1SE3IqJ7VH83ijiixqqQa7kJ0jsp3LcSMChQHWxL7YFK+sxIo -Z0tmPBHD+gQx3eJ6vW8yLY4Sd3CMnqZh6ZDeJASCrnZxwoMxMMa1cClTlLDIj7vA -kWzH5Lea6P4WY0jAuA5E8l8Yx2y2cc68toVt9XsguwKBgBtj6Oi2bu8JL/NReKrc -IbV0PPDiv7U7vNmgP11tNdsBHInr6+1DtvQfpHhLl+Uo563TbjJzQ2/+TMUAGs6T -27kWs1cV2b6gMGgEJMTUo6FNNSOgi1YjD4SdID8aK+mE7SwR/j/UTiADk16sqeOF -eOKwXz979QM0Ib5Q5s2tl39q +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDCx9oZn9tVOAXy +2XyjLv2JWYtn+cJ0CLPlym3A/r2pFAH4rQnoM2IAHcM5n6uWA9ke1bBUZM2+9UTj +y5jrNa+CGPYzsWnGOOpUcKgv3yaHlksBOi5xBPcx9UnraVpLiLLqcucCH1F1Soit +1Pg+OLwFqMW9rVNZYFFikc/KQO6/ZkKVGCVJyua4iVU5fANY0Je8gYTiobARfabd +QZgU8S/d2QGKcnFyxuYR81xaeOd6jJZ6ZzD3Hnl37cPHCksp+NQS7S7EKFhMNWT0 +iLe7NmWz2odUHA62tPpz0Aoma0L+yWoy1qrG+AERMjy0fwmXf7mM2hCDT3jEt3Nd ++0dzTp2zAgMBAAECggEACx5XX9EVNxccl9E8YSBEjruSzpueMvtwMXTNsQ+ZifY/ +ao+OGjgcpv8L7tUjeUu88Bqolxit+fGMPiiYEQ0eeKGuJCNDc3I6RhmsMBdf3quA +mpBUqFTtO2fSEWMRKXCjLejjMObSwow/oxSeGwcoDHam2v3y3Q43dxX1s4jjV/+H +uwgwghOqd9gTWeu7tOQefYkJ4Tsj6UMrf42LbSazjQmz+4sABmYv1TiuGW9Uj+vB +iV7Jozc9rVx4ZOhKrGxnM8kMsG6RWCfP5Nm3PUM/9tCzqNcPJCN3FyEcj2tfU/0I +CBuUqXaX4V/usg+TOf2tO2n/5TIZQozUatOAhWeJcQKBgQD3UJ9F6kIpkcO9qZLp +sLN0eVpt3hk2A//XV+QrKg8sYFxlYuX93TnF3q+V56h+UqXgCLnj0Q7MeAWLap2e +ApbumYRz8/qpthUqi0wyR8e8JEMDi3L5cOXNRYcVY2F3XKmxFXjfnNQ6gkms0Gfe +3Pni+q/xceQ7nhc0h/HAdNm3SwKBgQDJnvF6sW8bwamFoi0CWPOBcmb52QJ6tZ7h +Duh6fNZVE+FoRFv2q6PUNsm9rnTZtR7uevYcfnt2NrXNpsMQmnpaEU73nYWhiPn4 +zxaavAEFQPzUFaocYEAj5uXSKv1KNK2lvT9bjQFDT1lU1eginXJAbWa63zDnkV89 +AxH9LjeqOQKBgDtg8QzBROdkJwIHj81p7nw9krekRptQdIHIiXDPpVr7O9Pf3eaI +0hEu+Stdtne18juK/M605/+xpWsmyvcgGgrpcwLABmPu4sAXN9EuqMcEUc6tEYrQ +T2xskBVTihg1eEybIi1WIyJ1G6lRVE8O8TRNCidHOAwUVe/339RcedVnAoGAGcr7 +mXaZgDOGPFJC78nxXN4FznC0oH4blS8TDphp0vh4HZ6hJS1QCBX6OQnYaQGCs3+H +fJ2xra3SFD0BN16LyHnuYD8GmWOslufnPGRQvRtTPM6ItJibm/wt6nUVcijLDijn +sg6X2sSL6Q50Y/lAZH2aZs2ms/kk9ekuo/UFqgECgYEAlGWBKSsYH4OijwOSA54W +tHeKOMkv5DySAPQUhMPSE13y56XaoHdtl+wGElYQ2/lt1h8dhj0L04QZjhqkAJn3 +79xiYVOkKJvDjHCnjLIHkrDOKWBVApX31sD2uKl4BXRzLO+9iV+W67T89z71Ftdx +dQMjPQnK/1R3jqD9OWNr818= -----END PRIVATE KEY----- diff --git a/CertificateManagement/jwks/jwks.pem b/CertificateManagement/jwks/jwks.pem index 54a7ac7..7ce2cd2 100644 --- a/CertificateManagement/jwks/jwks.pem +++ b/CertificateManagement/jwks/jwks.pem @@ -1,26 +1,26 @@ -----BEGIN CERTIFICATE----- -MIIEUzCCAzugAwIBAgIURBmTv/F9+Hh6RpWiroet2lWA7z0wDQYJKoZIhvcNAQEL +MIIEUzCCAzugAwIBAgIUTEUY54KyzXuJI7iBJSlXPQSfV2owDQYJKoZIhvcNAQEL BQAwazEeMBwGA1UEAwwVTW9ja0RhdGFSZWNpcGllbnRKd2tzMQswCQYDVQQGEwJB VTEMMAoGA1UECAwDQUNUMREwDwYDVQQHDAhDYW5iZXJyYTENMAsGA1UECgwEQUND -QzEMMAoGA1UECwwDQ0RSMB4XDTIxMDUyNDA0MzEwOFoXDTIyMDYyODA0MzEwOFow +QzEMMAoGA1UECwwDQ0RSMB4XDTIyMDUxMzA0MTkxMVoXDTIzMDYxNzA0MTkxMVow azEeMBwGA1UEAwwVTW9ja0RhdGFSZWNpcGllbnRKd2tzMQswCQYDVQQGEwJBVTEM MAoGA1UECAwDQUNUMREwDwYDVQQHDAhDYW5iZXJyYTENMAsGA1UECgwEQUNDQzEM -MAoGA1UECwwDQ0RSMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Iv8 -ocA0NvV7dd9hHI+n21OuRD+9bnLw213Y3q7VFwg2tufu0Z8TPOoHDjWVkbxaq1K8 -nPDtBAdR5HXnbjXFxPGwRV8UgGMDSI6Z/M0j1bUGV9D9rukcvJ8Z7QpDbKuZzeIg -6LrXfIpvyNisEXjMJI14zz9dX1EtWUYQTRq5r2UF8C8pHE1yUtaVnsOZBLmLqMPO -PNG1JsK2WhL1uOa0ef+UTQSjN1fw5D2d9K8azUPQL2ecsJA/ZTDZovVzS0fP0MdR -XZ/uNRmaww2zg0tIJLQH1Z7AmwAP4LrPIGma6nWo6+57ZJ263k84o9fdR5+hVIcQ -DEGlKpZDoeNLOBg09wIDAQABo4HuMIHrMIGSBgNVHSMEgYowgYehb6RtMGsxHjAc +MAoGA1UECwwDQ0RSMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwsfa +GZ/bVTgF8tl8oy79iVmLZ/nCdAiz5cptwP69qRQB+K0J6DNiAB3DOZ+rlgPZHtWw +VGTNvvVE48uY6zWvghj2M7FpxjjqVHCoL98mh5ZLAToucQT3MfVJ62laS4iy6nLn +Ah9RdUqIrdT4Pji8BajFva1TWWBRYpHPykDuv2ZClRglScrmuIlVOXwDWNCXvIGE +4qGwEX2m3UGYFPEv3dkBinJxcsbmEfNcWnjneoyWemcw9x55d+3DxwpLKfjUEu0u +xChYTDVk9Ii3uzZls9qHVBwOtrT6c9AKJmtC/slqMtaqxvgBETI8tH8Jl3+5jNoQ +g094xLdzXftHc06dswIDAQABo4HuMIHrMIGSBgNVHSMEgYowgYehb6RtMGsxHjAc BgNVBAMMFU1vY2tEYXRhUmVjaXBpZW50SndrczELMAkGA1UEBhMCQVUxDDAKBgNV BAgMA0FDVDERMA8GA1UEBwwIQ2FuYmVycmExDTALBgNVBAoMBEFDQ0MxDDAKBgNV -BAsMA0NEUoIURBmTv/F9+Hh6RpWiroet2lWA7z0wCQYDVR0TBAIwADAOBgNVHQ8B +BAsMA0NEUoIUTEUY54KyzXuJI7iBJSlXPQSfV2owCQYDVR0TBAIwADAOBgNVHQ8B Af8EBAMCBeAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwEwIQYDVR0RBBowGIIWbW9j -a2RhdGFyZWNpcGllbnQuandrczANBgkqhkiG9w0BAQsFAAOCAQEABqSMYM7EFg9+ -SjKf4i3I54AYDwTbGtmkQP6WDqcbRgOGinqHPTxMbf1MbK9iHgHfkRFGTLHlGb0o -gsS76rvgo8yDPqDu7SFbri0CCPYFc0DU4fbPa0u6bGFZRajlUqqJ81T458Nk8Z2Q -95lBoaD43Ho8ruEdg0Bm4c5N84Hjxdi72L+qzseBabjsKfRrXpdepY5vbpR8mkQS -ye2mOvC2k0os0eAwcv+9CazTXAyd3hPjDtZfezMWdg+3pNRleyxcRyVX6z2ArZGY -+VLZzLhUHVMiUMsOAPikdj9pABuwjWJxA2wfkcqucJC0FsXKF7nuv18kH/OsNXwd -hGCTGcg2/Q== +a2RhdGFyZWNpcGllbnQuandrczANBgkqhkiG9w0BAQsFAAOCAQEAtlmdMjbws09E +V+UvqB6NDaAtc6iUByvfAP81m5i6e3P7JRNFvr6x7IFLR0Ul927t+I15PqGxOHoA +kKkN7oKOj9/FIcD8pzJydpLfJy6ApA2C5m9o3NDHQV1hHra+XX08r4dZocy2m6Gn +4FVKAefyhURxljQFaQi4WqKOwuoxHEwAsChnuwKOM5biID/RFXJcEA9ZMVL4OZEQ +SUd1uNKvxieiX3m8NpwUeUnrNlZjX5VvKadUzxjz3MQm+aS0A+q05WLyxuLOGurx +sNLQtROxPfI1rIJLNJID5Z6g4yPAMfwnJ9+ySWTe8VYWc/9skiQwt6kyif/fhcQx +kYW4Te1x0w== -----END CERTIFICATE----- diff --git a/CertificateManagement/jwks/jwks.pfx b/CertificateManagement/jwks/jwks.pfx new file mode 100644 index 0000000..d5fb751 Binary files /dev/null and b/CertificateManagement/jwks/jwks.pfx differ diff --git a/CertificateManagement/mtls/client.pfx b/CertificateManagement/mtls/client.pfx new file mode 100644 index 0000000..85e022e Binary files /dev/null and b/CertificateManagement/mtls/client.pfx differ diff --git a/CertificateManagement/tls/mock-data-recipient.cmd b/CertificateManagement/tls/mock-data-recipient.cmd index 04a96e6..4518260 100644 --- a/CertificateManagement/tls/mock-data-recipient.cmd +++ b/CertificateManagement/tls/mock-data-recipient.cmd @@ -1,5 +1,5 @@ openssl req -new -newkey rsa:2048 -keyout mock-data-recipient.key -sha256 -nodes -out mock-data-recipient.csr -config mock-data-recipient.cnf openssl req -in mock-data-recipient.csr -noout -text -openssl x509 -req -days 400 -in mock-data-recipient.csr -out mock-data-recipient.pem -extfile mock-data-recipient.ext -signkey mock-data-recipient.key +openssl x509 -req -days 400 -in mock-data-recipient.csr -CA ..\mtls\ca.pem -CAkey ..\mtls\ca.key -CAcreateserial -out mock-data-recipient.pem -extfile mock-data-recipient.ext openssl pkcs12 -inkey mock-data-recipient.key -in mock-data-recipient.pem -export -out mock-data-recipient.pfx openssl pkcs12 -in mock-data-recipient.pfx -noout -info \ No newline at end of file diff --git a/CertificateManagement/tls/mock-data-recipient.cnf b/CertificateManagement/tls/mock-data-recipient.cnf index f6741cf..dd1471f 100644 --- a/CertificateManagement/tls/mock-data-recipient.cnf +++ b/CertificateManagement/tls/mock-data-recipient.cnf @@ -1,10 +1,10 @@ [ req ] -default_bits = 2048 -distinguished_name = req_distinguished_name -prompt = no -req_extensions = req_ext +default_bits = 2048 +distinguished_name = req_distinguished_name +prompt = no +req_extensions = req_ext [ req_distinguished_name ] -commonName = localhost +commonName = mock-data-recipient countryName = AU stateOrProvinceName = ACT localityName = Canberra @@ -16,5 +16,5 @@ keyUsage = critical, nonRepudiation, digitalSignature, keyEnciphermen extendedKeyUsage = critical, serverAuth subjectAltName = @alt_names [alt_names] -DNS.1 = localhost -DNS.2 = datarecipient.mock +DNS.1 = mock-data-recipient +DNS.2 = localhost \ No newline at end of file diff --git a/CertificateManagement/tls/mock-data-recipient.csr b/CertificateManagement/tls/mock-data-recipient.csr index ee07a76..e83e56f 100644 --- a/CertificateManagement/tls/mock-data-recipient.csr +++ b/CertificateManagement/tls/mock-data-recipient.csr @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIDEjCCAfoCAQAwXzESMBAGA1UEAwwJbG9jYWxob3N0MQswCQYDVQQGEwJBVTEM -MAoGA1UECAwDQUNUMREwDwYDVQQHDAhDYW5iZXJyYTENMAsGA1UECgwEQUNDQzEM -MAoGA1UECwwDQ0RSMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2FNd -sdRWWxLVjdZvb6D7ZLTuii5PE4U1EVCio0ToccZbi9Ke+dji0G6sSUYhWl+xEStF -OOTI1SXF6cTn0LSOIuET/8slyQkY19NT4rJDHHrsZzI9M4Rwa8cHxMbqgBFyifIu -tjCLo5VM0DsW+LLd2dYFF1lBIHuRDn6Z++Mf3oLZ/kNNyMTTx+nH2yCbMKn1JR5S -6pj8qQgnfv6B2EaxoT82W4uVCavKfds1cd/AJnp7d9pbwcET8o7PmvXIOf8fdIXl -ZtlTxhByX2Cmnj0AET77JYO0Fl2w6c8VhASW7+1jl9U1Og3Cw0WE8ii6CXnprK46 -WYZWHD7Wp4wRXtdRnQIDAQABoG4wbAYJKoZIhvcNAQkOMV8wXTAJBgNVHRMEAjAA -MA4GA1UdDwEB/wQEAwIF4DAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATAoBgNVHREE -ITAfgglsb2NhbGhvc3SCEmRhdGFyZWNpcGllbnQubW9jazANBgkqhkiG9w0BAQsF -AAOCAQEAYuij4i97KxfvH69K8Xcrj13LSOJpSLmkUBiRERX3aGUFcyxH/kV2hQEu -M1F9047adVySQ9BPE6EKHpwU4zMfjfQ4Ny8EJqMEgzbemBnklKYlkg54TlsbM27n -P+G2YqU6CUNn74+dkeeP8gTG8qOqDZ9stnJ4ZvPDggTyptzVkd23PbUZILIT+mF+ -6vWUkm3uA8/V4I+UB5klSbGj1vZGLt1RNJBB9EVhDwZTMcKTYhcoqERZgMYIKTSQ -2wO/CJrOvWCGkWlxP1k/Kfu1M/nuuN4Z5oK2N850j1qy96oyT17eeMBAKE9gK+IU -QsdxoZjJKJxu+ePoFebDBMv1DdSHzw== +MIIDHTCCAgUCAQAwaTEcMBoGA1UEAwwTbW9jay1kYXRhLXJlY2lwaWVudDELMAkG +A1UEBhMCQVUxDDAKBgNVBAgMA0FDVDERMA8GA1UEBwwIQ2FuYmVycmExDTALBgNV +BAoMBEFDQ0MxDDAKBgNVBAsMA0NEUjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMamatLnO08pyoxAvgXXe0e30tLUjeuQM63JDihenPoKr7TKqRUm2xtD +zY7Ml9p4nx8v7HqhV7WbBLXVst+1dubh1Br6t9enZBWNdYfca7kF4Qk6TcY2vVtn +bqsln2UaEQvLEJ0a+G2TQx8RgHHH7r+2czeZlPiGyavlz/TwE4zLykTFp4HDdGsS +5sXFY0GF4HbIqF9xh9Niv+wVWtxLOXUee117zTrYTC2uNyJS9xr7KFvHbZtlgcBk +Y5gwx5rkHM1tbKIXaehHaRBZFysJu1VJCqHtZoo+mx0YmINle//HF7ngwNbuTMWb +c0Um8UKoXxemiX+3jg72AgsVzxOkkkcCAwEAAaBvMG0GCSqGSIb3DQEJDjFgMF4w +CQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH +AwEwKQYDVR0RBCIwIIITbW9jay1kYXRhLXJlY2lwaWVudIIJbG9jYWxob3N0MA0G +CSqGSIb3DQEBCwUAA4IBAQAEwKbreNrY+FgOjrr3oSC6Bq1H66fcS66jaw1V0Ndk +BRbQhkk9lNV7fvctkxxGMC3WBB+d7fJB341hVrCvoQsn6/jliTUGN2pATpTJb1he +1uk0Gqa5i7ERF7fRkETyV+g7yt2TAl4bnk6ai2YFQF/Nd2Gn9oR5S9dnuPihJ9mC +E0tlVSi8kE6aypWGdfeSj6m4RWZjUEeXrPVsO9VCgmmpZLOawNYCh8+mmKmBd1uS +FNlsL6m06mAdgrJ3DoHFSvcFhYLAFyxL+5zJfCvovQzG0zH/UExEQMD9s/8UBh7d +VJv1KQLwKJv8mcRAyU4vYC6K6w/6KBsI8brUk30q7kWR -----END CERTIFICATE REQUEST----- diff --git a/CertificateManagement/tls/mock-data-recipient.ext b/CertificateManagement/tls/mock-data-recipient.ext index 944625a..d0b3170 100644 --- a/CertificateManagement/tls/mock-data-recipient.ext +++ b/CertificateManagement/tls/mock-data-recipient.ext @@ -4,5 +4,6 @@ keyUsage = critical, nonRepudiation, digitalSignature, keyEnciphermen extendedKeyUsage = critical, serverAuth subjectAltName = @alt_names [alt_names] -DNS.1 = localhost -DNS.2 = datarecipient.mock +DNS.1 = mock-data-recipient +DNS.2 = localhost + diff --git a/CertificateManagement/tls/mock-data-recipient.key b/CertificateManagement/tls/mock-data-recipient.key index 3a480d6..fcbef04 100644 --- a/CertificateManagement/tls/mock-data-recipient.key +++ b/CertificateManagement/tls/mock-data-recipient.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDYU12x1FZbEtWN -1m9voPtktO6KLk8ThTURUKKjROhxxluL0p752OLQbqxJRiFaX7ERK0U45MjVJcXp -xOfQtI4i4RP/yyXJCRjX01PiskMceuxnMj0zhHBrxwfExuqAEXKJ8i62MIujlUzQ -Oxb4st3Z1gUXWUEge5EOfpn74x/egtn+Q03IxNPH6cfbIJswqfUlHlLqmPypCCd+ -/oHYRrGhPzZbi5UJq8p92zVx38Ament32lvBwRPyjs+a9cg5/x90heVm2VPGEHJf -YKaePQARPvslg7QWXbDpzxWEBJbv7WOX1TU6DcLDRYTyKLoJeemsrjpZhlYcPtan -jBFe11GdAgMBAAECggEBAKKjSrX/5kzihBv3NCDA70Bvp0fMOTd71sIF1cDadcfU -Uc91soA1R5FdI7qTN1Ay0XUPCyQTHcric0GmAIMwvAwNHHQbz3Stmjfpcg/l5f7r -jACqDMlGsR7WrEiNJJDUjUCZC/V92f5KqU2En2irUZANEBbVy9kYDZ7QIAT4ZWVr -qY6F9XRp3I2oLXp8EEp9bHxJG0Vy9iNDu/0pKnFHDppDyhUBok5AXx8cvKHAdHjX -8QmNExvmaxTA0GueEqUvxUt45i1b4zPwbPKKoSuSOnPbZBfLDluYDd52XIYTR/Gi -jo3JdR1e+S359P+Ri6hsqN+amdHhfy/9rEN2wJy5VgECgYEA648GLWhK9FfFCqCz -IRIW/Y4dbO3T4cguYArEXPVkU6RLh3vIzqqVMUJzEEmDLSBt/4v1vIKjLU9Btoq/ -a6xa+JJi0TtV5SPQb134Wxda2c93bpeRkWnyNymepE11oES+Pm5pe+Rfoo1OxP4X -wTsWORyqn5ksqdC/E6kD8wNGi/ECgYEA6xkTn62/0m4/nZVSnIr87BFCXak7q/3a -fVawZiwn6ATrg4R24WOwJ23jcxmppTjxdPjpqzZWryxnjEzyaVajTsTib7SgUSo7 -hKHEojMcpFWIvop1cxFOieK/3kHS2Ywp3YsOr51RPDM0Sts3xurxa5Vw6d5Cjqa1 -m6rtrsdVfG0CgYB3L77oasTCLUa9weHg8c5ALRAmdY+nxinw3oHMpz1ENPUicDeC -mj0y13Rw4UFGLAp8Ks0DvPXjjx6oxjtkt6iv7SGizGsBrcVhFCL9tCt72cWMZ5R4 -BytPTfe/GpJRrXa1EBi/XyYkkWsxsX9DfioYa7DJYC+BHOYRhItDAn1HgQKBgGq9 -IO6/mTb2PUXTtQVECV842tPhcSk+gUOk50QMSjYKfc9hhgQBGcpdFwZ8IUzVlLMS -DC1i52pzE7RcfzcaUd0CgPhMnvka3pjyRW+LGzb1ardv77FFq03pOEm1wwBopd1j -NFDBcU+Ow/A0pZdXtjKtT+2urrNLt2qs6WsQL5zlAoGBAI+LJQhmJwLoelFGc151 -/cv/82K3c/bestnR6bPi9sFNG684AiUVXshhciWmV6ZSBliagQxuKpew0TJqNotm -vNmYzq+rZxKjQN6rqK9BBvIT8oy9xR/Qeve+b3uKCx4XuEqnOu1zoIMdQC7gHjNt -ATArcejlf4D6sHAwRrAZSYRW +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDGpmrS5ztPKcqM +QL4F13tHt9LS1I3rkDOtyQ4oXpz6Cq+0yqkVJtsbQ82OzJfaeJ8fL+x6oVe1mwS1 +1bLftXbm4dQa+rfXp2QVjXWH3Gu5BeEJOk3GNr1bZ26rJZ9lGhELyxCdGvhtk0Mf +EYBxx+6/tnM3mZT4hsmr5c/08BOMy8pExaeBw3RrEubFxWNBheB2yKhfcYfTYr/s +FVrcSzl1Hntde8062EwtrjciUvca+yhbx22bZYHAZGOYMMea5BzNbWyiF2noR2kQ +WRcrCbtVSQqh7WaKPpsdGJiDZXv/xxe54MDW7kzFm3NFJvFCqF8Xpol/t44O9gIL +Fc8TpJJHAgMBAAECggEARpE9p3gvEHsnEdW56zdV+u8pPG33kHPkd9rRZbPejdCY +BGBt2i64bSIT9qNlWl25IQoUNqf0EXZlIPcuGNxMxc35XDAueLRlEGb1FnNN7SdS +fsWwdTZi5AKFRNUTn4W4Anl7iGPZVouWr4W3HDRK8t2sZlbvna28HI2B52AVgdEO +unvEGZ7lXCWvuWSEfkPOi/X8FW9iD8hxCPSWynRpYT8FU1oaX7SJzlFyEMcKNmcx +RFm1gtXIgqjsnq5MIo0fLed58lOGel8qASaDRygHeJr5yvUxeDhK8oOp40gaszyG +qtXdT/ytVoQVw4oCu7h2ay9x8BogE2R8JBR3aRpLUQKBgQDs5h2ikUvuEwIGaNdr +bOiu73PFp7bk234OD09CBdqjMxWoqwF15LY4lEiu6QgOmrWPQm7BJCQMiKzoVFfC +IfliaM/6Wt3dmSwEbWqYKiCHgVU1BUaELyK1Cl4DKrVf4CWx6ighxG2z3uJQD07m +KQu2EIJsgI49rjit2Sfih+eDWQKBgQDWqsx/duqIeg3orNiz8WulrAI6PfE0aWwl +iXMXHy082jzqjfom2IaWEcSfQhacZGoQkMlDolXL/nG9wHIDE6xOZm7j/bBRqwFZ +qK1I2fhs1fAXZCpFlIAMndg8RIg8/LRSsjwcaxkTlSCm06EamLPfGXvqa3BvSw9j +CJahs0AunwKBgQC+nLmjoL0zpl+uwJT0fwEKIOlKVJQ4uNNIhNEFEqjFP8lhmZbn +QUvNYqLI+f/doGYOCyoKhgXrf92AYrzqG2QJ5sPRcWOrdh+QwGlQXjUmUs44hzIi +EbsfaGQUsDyYFEbATORVpzON0vzN5kNZthUSPV5z50yMHK7GU0BgaXHCoQKBgC3j +0VemWjjWrsaAvMqq33JJNSiyOTAVIVNc8MeOmKMbnE4gD8viGdNW9Qt+m0rPhIUK +DpxwxZqYSERiMX1K5VjVOPtwLhMnVWCPWIvsXNkXWv4FIaxCNKV90M4BcIZpFzte +cs84beHrzVEciKIg5sLYtc7FLQH9r8ph+aGTqjLNAoGAa9FJBSn4aKFPXGqq6wcZ +r1y+qmQL8bUzxFTnIWq2G+FggNtPow1CiqU+Q3hgMoHWQ2P1xwVXT1MzaPAB7lxu +zvKevxXXmXE0GBvlvabrTDu0nbwzmLvVbKH5A6GUYFknOMS1vbCIvE12kSvrjyWS +NYCnmXVhcTvt9UwyRHQUrOo= -----END PRIVATE KEY----- diff --git a/CertificateManagement/tls/mock-data-recipient.pem b/CertificateManagement/tls/mock-data-recipient.pem index 8b38004..07052ea 100644 --- a/CertificateManagement/tls/mock-data-recipient.pem +++ b/CertificateManagement/tls/mock-data-recipient.pem @@ -1,25 +1,28 @@ -----BEGIN CERTIFICATE----- -MIIENDCCAxygAwIBAgIUZaqmrvVAMs2YIZict8IpRYq2GOYwDQYJKoZIhvcNAQEL -BQAwXzESMBAGA1UEAwwJbG9jYWxob3N0MQswCQYDVQQGEwJBVTEMMAoGA1UECAwD -QUNUMREwDwYDVQQHDAhDYW5iZXJyYTENMAsGA1UECgwEQUNDQzEMMAoGA1UECwwD -Q0RSMB4XDTIxMDQxNDEyMzMxNVoXDTIyMDUxOTEyMzMxNVowXzESMBAGA1UEAwwJ -bG9jYWxob3N0MQswCQYDVQQGEwJBVTEMMAoGA1UECAwDQUNUMREwDwYDVQQHDAhD -YW5iZXJyYTENMAsGA1UECgwEQUNDQzEMMAoGA1UECwwDQ0RSMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2FNdsdRWWxLVjdZvb6D7ZLTuii5PE4U1EVCi -o0ToccZbi9Ke+dji0G6sSUYhWl+xEStFOOTI1SXF6cTn0LSOIuET/8slyQkY19NT -4rJDHHrsZzI9M4Rwa8cHxMbqgBFyifIutjCLo5VM0DsW+LLd2dYFF1lBIHuRDn6Z -++Mf3oLZ/kNNyMTTx+nH2yCbMKn1JR5S6pj8qQgnfv6B2EaxoT82W4uVCavKfds1 -cd/AJnp7d9pbwcET8o7PmvXIOf8fdIXlZtlTxhByX2Cmnj0AET77JYO0Fl2w6c8V -hASW7+1jl9U1Og3Cw0WE8ii6CXnprK46WYZWHD7Wp4wRXtdRnQIDAQABo4HnMIHk -MIGEBgNVHSMEfTB7oWOkYTBfMRIwEAYDVQQDDAlsb2NhbGhvc3QxCzAJBgNVBAYT -AkFVMQwwCgYDVQQIDANBQ1QxETAPBgNVBAcMCENhbmJlcnJhMQ0wCwYDVQQKDARB -Q0NDMQwwCgYDVQQLDANDRFKCFGWqpq71QDLNmCGYnLfCKUWKthjmMAkGA1UdEwQC -MAAwDgYDVR0PAQH/BAQDAgXgMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMCgGA1Ud -EQQhMB+CCWxvY2FsaG9zdIISZGF0YXJlY2lwaWVudC5tb2NrMA0GCSqGSIb3DQEB -CwUAA4IBAQC2Kao5gLZ04v6GVjVPiITCRY22YVLgCYgjktztKm0osDdcgFgdgcpw -OVptIW3RNj3ikVoMARR0sytUdObw6QSg5aKORoYfyftfnXzYWyHKoznVgFaMmNkl -MGeIMGF1nEX/5WYBKZkwSSmNVUylQCazmxby7qD9JS1rAPoIc/La9+P2xMS3qBzy -GBOwWISJI4rwVmZPexv+bxyQ4aTG8hGU5P9o5yx95aVkNVADIqkfaX8w1hWl870Y -5KGu1w2RbxDM7O0u/gxYeWFhPXvbxE5mAc8BgLBtoseQY4Eyo/YiC8zK8Lc+topA -dM1ebYL/t2dVg6GARrC680MhzKRWgCfm +MIIE2jCCAsKgAwIBAgIUB5/EJp1DnM5zM6K6DwzgcAei0PwwDQYJKoZIhvcNAQEL +BQAwYTELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA0FDVDERMA8GA1UEBwwIQ2FuYmVy +cmExDTALBgNVBAoMBEFDQ0MxDDAKBgNVBAsMA0NEUjEUMBIGA1UEAwwLTW9jayBD +RFIgQ0EwHhcNMjIwNTIzMDUwODMxWhcNMjMwNjI3MDUwODMxWjBpMRwwGgYDVQQD +DBNtb2NrLWRhdGEtcmVjaXBpZW50MQswCQYDVQQGEwJBVTEMMAoGA1UECAwDQUNU +MREwDwYDVQQHDAhDYW5iZXJyYTENMAsGA1UECgwEQUNDQzEMMAoGA1UECwwDQ0RS +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxqZq0uc7TynKjEC+Bdd7 +R7fS0tSN65AzrckOKF6c+gqvtMqpFSbbG0PNjsyX2nifHy/seqFXtZsEtdWy37V2 +5uHUGvq316dkFY11h9xruQXhCTpNxja9W2duqyWfZRoRC8sQnRr4bZNDHxGAccfu +v7ZzN5mU+IbJq+XP9PATjMvKRMWngcN0axLmxcVjQYXgdsioX3GH02K/7BVa3Es5 +dR57XXvNOthMLa43IlL3GvsoW8dtm2WBwGRjmDDHmuQczW1sohdp6EdpEFkXKwm7 +VUkKoe1mij6bHRiYg2V7/8cXueDA1u5MxZtzRSbxQqhfF6aJf7eODvYCCxXPE6SS +RwIDAQABo4GBMH8wHwYDVR0jBBgwFoAUgwae2roI5isJUghibN4UpBd2dVEwCQYD +VR0TBAIwADAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwEw +KQYDVR0RBCIwIIITbW9jay1kYXRhLXJlY2lwaWVudIIJbG9jYWxob3N0MA0GCSqG +SIb3DQEBCwUAA4ICAQA6hQkTNLsN4x0d1a999ORov0qqjbbVaXQ108WKQEwD0s9e +ywwYh14akk7E6O0nWk8R9B27jnm5GZztSRRkmf170PDMhrOZ7+oauT2prpe1mp1K +f8W7va4shuaidfTl5oh6l+6+CEohNsJuUQZvK/V7ubKE5wBQLIi2n90uCcrAat1H +ciLjDRA+mpoBp7FvhbZlFVVQirrtEUZ4nZFgmMMr3+CmT/FGclO5tRsGozzXB7H2 +m0AWIE7nwKBWxJMSL6yTAVpXgJHc8MvLrEvrOiNAPlWHs8qWZdpv2a7Nm3W2OZ/o +4eGYNOKcNjPvEu3r2tfm9oF7R4fUwQndH7BvNtQlcpMwFtKjC9zR5kPmEtfW/aUl +GiSy94ZIKxSs78QI7TXDD544IpEGdD4A5xZS3mhoYkI6JKS/ps+7Bv5hk89kWiZh +KyT37HeDL3AmPEOZfoCyT2Ol/W5J7YzG2tVRxTOk+MR5va5NxSEdEj1rbvS9Kxgj +7QWYFaRfF9Q7KMHyMg8KuCtYhJBO68X1GFPJm4G3i6AWkbLDtjSRNyB8k1WleygW ++lhpQK5B1T2ZMtN2iVvt7xXRBYkRxRytM0dgbSrCt73Phwb9GSVT+3FEK/jVB0Kj +LiGkNVQSLmLfMg79trrvOfCZI4iIoD/IIY97hp+JqsEVDPIs7kX9Vvo091io2A== -----END CERTIFICATE----- diff --git a/CertificateManagement/tls/mock-data-recipient.pfx b/CertificateManagement/tls/mock-data-recipient.pfx new file mode 100644 index 0000000..a039449 Binary files /dev/null and b/CertificateManagement/tls/mock-data-recipient.pfx differ diff --git a/Help/container/HELP.md b/Help/container/HELP.md new file mode 100644 index 0000000..aa2025c --- /dev/null +++ b/Help/container/HELP.md @@ -0,0 +1,107 @@ +

Use the pre-built image for this solution

+ +
+

1. Pull the latest image from Docker Hub

+ + + docker pull consumerdataright/mock-data-recipient + + +
+

2. Run the Mock Data Recipient container

+ + + docker run -d -h mock-data-recipient -p 9001:9001 --add-host=host.docker.internal:host-gateway --name mock-data-recipient consumerdataright/mock-data-recipient +

+ docker run -d -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Pa{}w0rd2019" -p 1433:1433 --name sql1 -h sql1 -d mcr.microsoft.com/mssql/server:2019-latest +

+ Please note - This docker compose file utilises the Microsoft SQL Server Image from Docker Hub.
+ The Microsoft EULA for the Microsoft SQL Server Image must be accepted to continue.
+ See the Microsoft SQL Server Image on Docker Hub for more information.
+ Using the above command from a MS Windows command prompt will run the database.
+
+ +
+

3. Use the docker compose file to run a multi-container mock CDR Ecosystem.

+ + + The docker compose file can be used to run multiple containers from the Mock CDR Ecosystem, by starting the docker desktop + (if using a non MS Windows environment, you will need to add this route to the network), this will be added to your hosts file and is used for inter container connectivity via your host IP Address, eg C:\Windows\System32\drivers\etc\hosts + + +
+ + + ###.###.###.### host.docker.internal + + +
+ +[MS Docker Desktop](./images/docker-desktop.png) + +

4. Execute the docker compose file, the default configuration is to run all mock solutions and executing the comand below will run all the solutions. +

+ + + docker-compose up + +
+
+ + + Please note - This docker compose file utilises the Microsoft SQL Server Image from Docker Hub.
+ The Microsoft EULA for the Microsoft SQL Server Image must be accepted to continue.
+ Replace this unset ACCEPT_MSSQL_EULA variable with a Y if you accept the EULA. eg ACCEPT_EULA=Y
+ See the Microsoft SQL Server Image on Docker Hub for more information.
+
+ +[Containers Running](./images/containers-running.png) + + + Should you wish to switch out your own solution, remark the relevant code out of this file.
+ In this example we will be simulating the switching out of our Mock Data Recipient, we are using the
+ database connection string Server=host.docker.internal and the endpoints shown below to
+ connect to the running containers, this will result in the Mock Data Recipient running in MS Visual Studio,
+ connected to the Mock Register and the Mock Data Holder running in docker.
+ For details on how to run a Mock solution in MS Visual Studio + see help guide +
+
+
+ +[Mock Data Recipient switched out settings](./images/mdr-switch-out-settings.png) + + + How to build your own image instead of downloading it from docker hub.
+ navigate to .\mock-data-recipient\Source
+ open a command prompt and execute the following;
+ docker build -f Dockerfile.container -t mock-data-recipient .
+ docker run -d -h mdr-host -p 9001:9001 --add-host=host.docker.internal:host-gateway --name mock-data-recipient mock-data-recipient

+ Please note - By default, the container above will be using a MS SQL database container, using this command from a MS Windows command prompt will run the database,
+ docker run -d -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Pa{}w0rd2019" -p 1433:1433 --name sql1 -h sql1 -d mcr.microsoft.com/mssql/server:2019-latest +
+ + + You can connect to the MS SQL database container from MS Sql Server Management Studio (SSMS) using + the following settings;
+ Server type: Database Engine
+ Server name: localhost
+ Authentication: SQL Server Authentication
+ Login: sa
+ Password: Pa{}w0rd2019
+
+
+ +[SSMS Login Error](./images/ssms-login-error.png) + +

+ (Please note - if the above error occurs whilst trying to connect to the MS SQL container, the SQL Server Service MUST BE STOPPED, you can do this from SQL Server Manager) +

+ +

5. The running solution

+ + + Our switched out Mock Data Recipient solution will now be running. + + +[The Mock Data Recipient solution](./images/mdr-switch-out-running.png) diff --git a/Help/container/images/containers-running.png b/Help/container/images/containers-running.png new file mode 100644 index 0000000..a89ab4e Binary files /dev/null and b/Help/container/images/containers-running.png differ diff --git a/Help/container/images/docker-desktop.png b/Help/container/images/docker-desktop.png new file mode 100644 index 0000000..b53d6cf Binary files /dev/null and b/Help/container/images/docker-desktop.png differ diff --git a/Help/container/images/docker-stats.png b/Help/container/images/docker-stats.png new file mode 100644 index 0000000..48a8ebb Binary files /dev/null and b/Help/container/images/docker-stats.png differ diff --git a/Help/container/images/mdr-switch-out-running.png b/Help/container/images/mdr-switch-out-running.png new file mode 100644 index 0000000..9162d0c Binary files /dev/null and b/Help/container/images/mdr-switch-out-running.png differ diff --git a/Help/container/images/mdr-switch-out-settings.png b/Help/container/images/mdr-switch-out-settings.png new file mode 100644 index 0000000..169d286 Binary files /dev/null and b/Help/container/images/mdr-switch-out-settings.png differ diff --git a/Help/container/images/ssms-login-error.png b/Help/container/images/ssms-login-error.png new file mode 100644 index 0000000..2c10ab5 Binary files /dev/null and b/Help/container/images/ssms-login-error.png differ diff --git a/Help/debugging/HELP.md b/Help/debugging/HELP.md new file mode 100644 index 0000000..c88f875 --- /dev/null +++ b/Help/debugging/HELP.md @@ -0,0 +1,67 @@ +

To get started, clone the source code

+
+1. Create a folder called CDR
+2. Navigate to this folder
+3. Clone the repo as a subfolder of this folder using the following command;
+
+git clone https://github.com/ConsumerDataRight/mock-data-recipient.git
+
+4. Install the required certificates. See certificate details here.
+5. Start the projects in the solution, can be done in multiple ways, examples below are from .Net command line and using MS Visual Studio
+
+ +

.Net command line

+
+

1. Download and install the free MS Windows Terminal +
+2. Use the Start-Data-Recipient batch file to build and run the required projects to start the Mock Data Recipient, +
+this will create the LocalDB instance by default and seed the database with the supplied sample data. +

+ +[Start projects from .Net CLI](./images/DotNet-CLI-Running.png) + +

LocalDB is installed as part of MS Visual Studio if using MS VSCode then adding the MS SQL extension includes the LocalDB Instance.

+

You can connect to the database from MS Visual Studio using the SQL Explorer, or from MS SQL Server Management Studio (SSMS) using + the following settings;
+ Server type: Database Engine
+ Server name: (LocalDB)\MSSQLLocalDB
+ Authentication: Windows Authentication
+

+
+ +

MS Visual Studio

+
+

To launch the application using MS Visual Studio,

+ +

1. Select the project to start.

+ +[Start the projects](./images/MS-Visual-Studio-Start.png) + +

2. Then start the project (Ctrl + F5 or F5 or Debug > Start Debugging).

+ +[Projects running](./images/MS-Visual-Studio-Running.png) + +An output window will be launched for the selected project started.
+This will show the logging messages as sent to the console of the running project. +
+ +

Debugging the running project using MS Visual Studio can be performed as follows;

+ +

1. Select the project you want to debug and place the appropriate breakpoints as desired.

+ +[Place breakpoint(s) in the projects](./images/Debug-using-MS-Visual-Studio-pt1.png) + +

2. Start a new debug instance for the selected project (F5 or Debug > Start Debugging).

+
+ A new output window for the debug project will be started. +
+
+ +[Start a new debug instance](./images/Debug-using-MS-Visual-Studio-pt2.png) + +

The browser window will be started with the Mock Data Recipient solution.

+ +[Newly started output window](./images/Launch-application-in-browser.png) + +
\ No newline at end of file diff --git a/Help/debugging/images/Debug-using-MS-Visual-Studio-pt1.png b/Help/debugging/images/Debug-using-MS-Visual-Studio-pt1.png new file mode 100644 index 0000000..6ff90d6 Binary files /dev/null and b/Help/debugging/images/Debug-using-MS-Visual-Studio-pt1.png differ diff --git a/Help/debugging/images/Debug-using-MS-Visual-Studio-pt2.png b/Help/debugging/images/Debug-using-MS-Visual-Studio-pt2.png new file mode 100644 index 0000000..9b02177 Binary files /dev/null and b/Help/debugging/images/Debug-using-MS-Visual-Studio-pt2.png differ diff --git a/Help/debugging/images/DotNet-CLI-Running.png b/Help/debugging/images/DotNet-CLI-Running.png new file mode 100644 index 0000000..b529fdc Binary files /dev/null and b/Help/debugging/images/DotNet-CLI-Running.png differ diff --git a/Help/debugging/images/Launch-application-in-browser.png b/Help/debugging/images/Launch-application-in-browser.png new file mode 100644 index 0000000..c20c1e8 Binary files /dev/null and b/Help/debugging/images/Launch-application-in-browser.png differ diff --git a/Help/debugging/images/MS-Visual-Studio-Running.png b/Help/debugging/images/MS-Visual-Studio-Running.png new file mode 100644 index 0000000..92c14dc Binary files /dev/null and b/Help/debugging/images/MS-Visual-Studio-Running.png differ diff --git a/Help/debugging/images/MS-Visual-Studio-Start.png b/Help/debugging/images/MS-Visual-Studio-Start.png new file mode 100644 index 0000000..bccde55 Binary files /dev/null and b/Help/debugging/images/MS-Visual-Studio-Start.png differ diff --git a/LICENSE b/LICENSE index aa21f3d..f8ca315 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Commonwealth of Australia +Copyright (c) 2022 Commonwealth of Australia Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index e215c08..79238ef 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Consumer Data Right Logo](https://raw.githubusercontent.com/ConsumerDataRight/mock-data-recipient/main/cdr-logo.png) -[![Consumer Data Standards 1.11.0](https://img.shields.io/badge/Consumer%20Data%20Standards-v1.11.0-blue.svg)](https://consumerdatastandardsaustralia.github.io/standards/includes/releasenotes/releasenotes.1.11.0.html#v1-11-0-release-notes) +[![Consumer Data Standards v1.16.0](https://img.shields.io/badge/Consumer%20Data%20Standards-v1.16.0-blue.svg)](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.16.0/#introduction) [![Conformance Test Suite 3.2](https://img.shields.io/badge/Conformance%20Test%20Suite-v3.2-darkblue.svg)](https://www.cdr.gov.au/for-providers/conformance-test-suite-data-recipients) [![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/) @@ -13,11 +13,12 @@ This project includes source code, documentation and instructions for a Consumer This repository contains a mock implementation of a Mock Data Recipient and is offered to help the community in the development and testing of their CDR solutions. ## Mock Data Recipient - Alignment -The Mock Data Recipient aligns to [v1.11.0](https://consumerdatastandardsaustralia.github.io/standards/includes/releasenotes/releasenotes.1.11.0.html#v1-11-0-release-notes) of the [Consumer Data Standards](https://consumerdatastandardsaustralia.github.io/standards). +The Mock Data Recipient aligns to [v1.16.0](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.16.0/#introduction) of the [Consumer Data Standards](https://consumerdatastandardsaustralia.github.io/standards/#introduction). The Mock Data Recipient passed v3.2 of the [Conformance Test Suite for Data Recipients](https://www.cdr.gov.au/for-providers/conformance-test-suite-data-recipients). +The Mock Data Recipient can connect to and complete authentication against both [FAPI 1.0 Migration Phase 1 and Phase 2](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.16.0/#authentication-flows) compliant data holders. ## Getting Started -The Mock Data Recipient was built using the [Mock Register](https://github.com/ConsumerDataRight/mock-register) and the [Mock Data Holder](https://github.com/ConsumerDataRight/mock-data-holder). You can swap out any of the Mock Data Holder, Mock Data Register and Mock Data Recipient solutions with a solution of your own. +The Mock Data Recipient was built using the [Mock Register](https://github.com/ConsumerDataRight/mock-register), the [Mock Data Holder](https://github.com/ConsumerDataRight/mock-data-holder) and the [Mock Data Holder Energy](https://github.com/ConsumerDataRight/mock-data-holder-energy). You can swap out any of the Mock Data Holders, Mock Data Register and Mock Data Recipient solutions with a solution of your own. There are a number of ways that the artefacts within this project can be used: 1. Build and deploy the source code @@ -35,25 +36,21 @@ git clone https://github.com/ConsumerDataRight/mock-data-recipient.git Set your debug profile to CDR.DataRecipient.Web ```` +To get help on launching and debugging the solution, see the [help guide](./Help/debugging/HELP.md). + If you would like to contribute features or fixes back to the Mock Data Recipient repository, consult the [contributing guidelines](CONTRIBUTING.md). ### Use the pre-built image A version of the Mock Data Recipient is built into a single Docker image that is made available via [docker hub](https://hub.docker.com/r/consumerdataright/mock-data-recipient). -The container can simply be run by pulling and running the latest image using the following Docker commands: - #### Pull the latest image ``` docker pull consumerdataright/mock-data-recipient ``` -#### Run the Mock Recipient container - -``` -docker run -d -h mock-data-recipient -p 9001:9001 --name mock-data-recipient consumerdataright/mock-data-recipient -``` +To get help on launching and debugging the solutions as containers and switching out your solution(s), see the [help guide](./Help/container/HELP.md). #### Certificate Management @@ -62,27 +59,15 @@ Consult the [Certificate Management](CertificateManagement/README.md) documentat ### Use the docker compose file to run a multi-container mock CDR Ecosystem The [docker compose file](Source/DockerCompose/docker-compose.yml) can be used to run multiple containers from the Mock CDR Ecosystem. -1. Add the following to your hosts file, eg C:\Windows\System32\drivers\etc\hosts -```` -127.0.0.1 mock-data-holder -127.0.0.1 mock-data-recipient -127.0.0.1 mock-register -```` -2. Flush the DNS cache, on Windows use: -```` -ipconfig /flushdns -```` -3. Run the [docker compose file](Source/DockerCompose/docker-compose.yml) -```` -docker-compose up -```` -Update the docker compose file if you would like to swap out one of the mock solutions with a solution of your own. +**Note:** the [docker compose file](Source/DockerCompose/docker-compose.yml) utilises the Microsoft SQL Server Image from Docker Hub. The Microsoft EULA for the Microsoft SQL Server Image must be accepted to use the [docker compose file](Source/DockerCompose/docker-compose.yml). See the Microsoft SQL Server Image on Docker Hub for more information. + +To get help on launching and debugging the solutions as containers and switching out your solution(s), see the [help guide](./Help/container/HELP.md). ## Mock Data Recipient - Architecture The following diagram outlines the high level architecture of the Mock Data Recipient: -![Mock Recipient - Architecture](https://raw.githubusercontent.com/ConsumerDataRight/mock-data-recipient/main/mock-data-recipient-architecture.png) +[Mock Data Recipient - Architecture](https://raw.githubusercontent.com/ConsumerDataRight/mock-data-recipient/main/mock-data-recipient-architecture.png) ## Mock Data Recipient - Components The Mock Data Recipient contains the following components: @@ -92,15 +77,16 @@ The Mock Data Recipient contains the following components: - Contains the user interface for testing a variety of interactions with participants, including: - Get Data Holder Brands - Get SSA - - Dynamic Client Registation - - Consent and Authorisation + - Dynamic Client Registration + - Consent and Authorisation. Supports [FAPI 1.0 Migration Phase 1](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.16.0/#authentication-flows) - Consumer Data Sharing - - PAR + - OIDC Authentication can be enabled in appsettings by including the issuer details. + - Pushed Authorisation Request (PAR). Supports [FAPI 1.0 Migration Phase 2](https://consumerdatastandardsaustralia.github.io/standards-archives/standards-1.16.0/#authentication-flows) - Also contains the JWKS and CDR Arrangement Revocation endpoints. - SDK - Used internally within the Mock Data Recipient to simplify interactions with the Register and Data Holders. - Repository - - An in memory SQLite repository is included that contains local data used within the Mock Data Recipient. + - A SQL repository is included that contains local data used within the Mock Data Recipient. - Includes the following collections: - `data-holder-brands` - populated when a response is received from the Register's `Get Data Holder Brands` API. - `client-registrations` - populated when a response is received from a successful DCR request to a Data Holder. @@ -108,11 +94,11 @@ The Mock Data Recipient contains the following components: ## Technology Stack The following technologies have been used to build the Mock Data Recipient: -- The source code has been written in `C#` using the `.NET 5` framework. -- The Repository utilises a `SQLite` instance. +- The source code has been written in `C#` using the `.Net 6` framework. +- The Repository utilises a `SQL` instance. # Testing -The Mock Data Recipient has been built as a test harness to demonstrate the interactions between the Register and Data Holders. The Mock Data Recipient allows the end user to test the various interactions by changing input values, executing and viewing the response. The Mock Data Recipient requires a [Mock Register](https://github.com/ConsumerDataRight/mock-register) and a [Mock Data Holder](https://github.com/ConsumerDataRight/mock-data-holder) to completely mimic the CDR Ecosystem. You can swap out any of the Mock Data Holder, Mock Data Register and Mock Data Recipient solutions with a solution of your own. +The Mock Data Recipient has been built as a test harness to demonstrate the interactions between the Register and Data Holders. The Mock Data Recipient allows the end user to test the various interactions by changing input values, executing and viewing the response. The Mock Data Recipient requires a [Mock Register](https://github.com/ConsumerDataRight/mock-register), a [Mock Data Holder](https://github.com/ConsumerDataRight/mock-data-holder) and a [Mock Data Holder Energy](https://github.com/ConsumerDataRight/mock-data-holder-energy) to completely mimic the CDR Ecosystem. You can [swap out](./containerhelp/HELP.md) any of the Mock Data Holders, Mock Data Register and Mock Data Recipient solutions with a solution of your own. Use the Consents and Authorisation flow when testing against data holders that have implemented FAPI 1.0 Migration Phase 1. Use the Pushed Authorisation Request (PAR) flow when testing against data holders that have implemented FAPI 1.0 Migration Phase 2. # Contribute We encourage contributions from the community. See our [contributing guidelines](CONTRIBUTING.md). @@ -124,4 +110,4 @@ This project has adopted the **Contributor Covenant**. For more information see [MIT License](./LICENSE) # Notes -The Mock Data Recipient is provided as a development tool only. It conforms to the Consumer Data Standards and Register Design. +The Mock Data Recipient is provided as a development tool only. It conforms to the Consumer Data Standards. \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/AATestPlaywrightInstallation.cs b/Source/CDR.DataRecipient.E2ETests/AATestPlaywrightInstallation.cs new file mode 100644 index 0000000..1cec90b --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/AATestPlaywrightInstallation.cs @@ -0,0 +1,25 @@ +using System.Threading.Tasks; +using Xunit; + +#nullable enable + +namespace CDR.DataRecipient.E2ETests +{ + public class AATestPlaywrightInstallation : BaseTest_v2, IClassFixture + { + [Fact] + public async Task ShouldDisplayGoogleHomePage() + { + await TestAsync($"{nameof(AATestPlaywrightInstallation)} - {nameof(ShouldDisplayGoogleHomePage)}", async (page) => + { + // Act - Goto Google.com + var resp = await page.GotoAsync("https://www.google.com"); + await page.ClickAsync(":nth-match(:text(\"I'm Feeling Lucky\"), 2)"); + + // Assert + Assert.NotNull(resp); + Assert.True(resp != null && resp.Status == 200); + }); + } + } +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/BaseTest.cs b/Source/CDR.DataRecipient.E2ETests/BaseTest.cs index 5d81cfc..e39627b 100644 --- a/Source/CDR.DataRecipient.E2ETests/BaseTest.cs +++ b/Source/CDR.DataRecipient.E2ETests/BaseTest.cs @@ -1,4 +1,12 @@ -// #define TEST_DEBUG_MODE +#undef DEPRECATED // instead see BaseTest_v2 +#if DEPRECATED + +// #define TEST_DEBUG_MODE // Run Playwright in non-headless mode for debugging purposes (ie show a browser) + +// In docker (Ubuntu container) Playwright will fail if running in non-headless mode, so we ensure TEST_DEBUG_MODE is undef'ed +#if !DEBUG +#undef TEST_DEBUG_MODE +#endif using System; using System.IO; @@ -6,6 +14,7 @@ using System.Threading.Tasks; using FluentAssertions; using FluentAssertions.Execution; +using Microsoft.Data.SqlClient; using Microsoft.Extensions.Configuration; using Microsoft.Playwright; using Newtonsoft.Json; @@ -19,18 +28,66 @@ namespace CDR.DataRecipient.E2ETests // Put all tests in same collection because we need them to run sequentially since some tests are mutating DB. [Collection("E2ETests")] [TestCaseOrderer("CDR.DataRecipient.E2ETests.XUnit.Orderers.AlphabeticalOrderer", "CDR.DataRecipient.E2ETests")] + [DisplayTestMethodName] public class BaseTest { + // Customers + public const string CUSTOMERID_BANKING = "jwilson"; + public const string CUSTOMERACCOUNTS_BANKING = "Personal Loan xxx-xxx xxxxx987,Transactions and Savings Account xxx-xxx xxxxx988"; + public const string CUSTOMERID_ENERGY = "mmoss"; + public const string CUSTOMERACCOUNTS_ENERGY = "'ELECTRICITY ACCOUNT','ELECTRICITY ACCOUNT 2',ELECTRICITY ACCOUNT 3,ELECTRICITY ACCOUNT 4,ELECTRICITY ACCOUNT 5,ELECTRICITY ACCOUNT 6,ELECTRICITY ACCOUNT 7,ELECTRICITY ACCOUNT 8,ELECTRICITY ACCOUNT 9,ELECTRICITY ACCOUNT 10,ELECTRICITY ACCOUNT 11,ELECTRICITY ACCOUNT 12,ELECTRICITY ACCOUNT 13,ELECTRICITY ACCOUNT 14,ELECTRICITY ACCOUNT 15,ELECTRICITY ACCOUNT 16,ELECTRICITY ACCOUNT 17,ELECTRICITY ACCOUNT 18,ELECTRICITY ACCOUNT 19,ELECTRICITY ACCOUNT 20,ELECTRICITY ACCOUNT 21"; + + // Data Holder + public const string DH_BRANDID = "804fc2fb-18a7-4235-9a49-2af393d18bc7"; + public const string DH_BRANDID_ENERGY = "cfcaf0df-401b-47f2-98af-94787289eca8"; // Mock Data Holder (Energy) + + // Data Recipient + public const string DR_BRANDID = "ffb1c8ba-279e-44d8-96f0-1bc34a6b436f"; + public const string DR_SOFTWAREPRODUCTID = "c6327f87-687a-4369-99a4-eaacd3bb8210"; + + // URLs + static public string REGISTER_MTLS_BaseURL => Configuration["MTLS_BaseURL"] + ?? throw new Exception($"{nameof(REGISTER_MTLS_BaseURL)} - configuration setting not found"); + + static public string REGISTER_IDENTITYSERVER_URL = REGISTER_MTLS_BaseURL + "/idp/connect/token"; + + // Client certificates + protected const string CERTIFICATE_FILENAME = "Certificates/client.pfx"; + protected const string CERTIFICATE_PASSWORD = "#M0ckDataRecipient#"; + + public const string JWT_CERTIFICATE_FILENAME = "Certificates/jwks.pfx"; + public const string JWT_CERTIFICATE_PASSWORD = "#M0ckDataRecipient#"; + + public bool CreateMedia { get; set; } = true; + // Test settings. + static public bool CREATE_MEDIA => Configuration.GetValue("CreateMedia", true); + static public int TEST_TIMEOUT => Configuration.GetValue("TestTimeout", 30000); + // URL of the web UI - protected const string WEB_URL = "https://localhost:9001"; + static public string WEB_URL => Configuration["Web_URL"] + ?? throw new Exception($"{nameof(WEB_URL)} - configuration setting not found"); + + // Hostnames + static public string HOSTNAME_REGISTER => Configuration["Hostnames:Register"] + ?? throw new Exception($"{nameof(HOSTNAME_REGISTER)} - configuration setting not found"); + static public string HOSTNAME_DATAHOLDER => Configuration["Hostnames:DataHolder"] + ?? throw new Exception($"{nameof(HOSTNAME_DATAHOLDER)} - configuration setting not found"); + static public string HOSTNAME_DATAHOLDER_ENERGY => Configuration["Hostnames:DataHolderEnergy"] + ?? throw new Exception($"{nameof(HOSTNAME_DATAHOLDER_ENERGY)} - configuration setting not found"); + static public string HOSTNAME_DATARECIPIENT => Configuration["Hostnames:DataRecipient"] + ?? throw new Exception($"{nameof(HOSTNAME_DATARECIPIENT)} - configuration setting not found"); // Connection strings static public string DATAHOLDER_CONNECTIONSTRING => Configuration["ConnectionStrings:DataHolder"] ?? throw new Exception($"{nameof(DATAHOLDER_CONNECTIONSTRING)} - configuration setting not found"); + static public string DATAHOLDER_ENERGY_CONNECTIONSTRING => Configuration["ConnectionStrings:DataHolderEnergy"] + ?? throw new Exception($"{nameof(DATAHOLDER_ENERGY_CONNECTIONSTRING)} - configuration setting not found"); static public string DATAHOLDER_IDENTITYSERVER_CONNECTIONSTRING => Configuration["ConnectionStrings:DataHolderIdentityServer"] ?? throw new Exception($"{nameof(DATAHOLDER_IDENTITYSERVER_CONNECTIONSTRING)} - configuration setting not found"); + static public string DATAHOLDER_ENERGY_IDENTITYSERVER_CONNECTIONSTRING => Configuration["ConnectionStrings:DataHolderEnergyIdentityServer"] + ?? throw new Exception($"{nameof(DATAHOLDER_ENERGY_IDENTITYSERVER_CONNECTIONSTRING)} - configuration setting not found"); static public string REGISTER_CONNECTIONSTRING => Configuration["ConnectionStrings:Register"] ?? throw new Exception($"{nameof(REGISTER_CONNECTIONSTRING)} - configuration setting not found"); static public string DATARECIPIENT_CONNECTIONSTRING => Configuration["ConnectionStrings:DataRecipient"] @@ -62,6 +119,107 @@ static protected IConfigurationRoot Configuration } } + protected BaseTest() + { + // Default from config. + this.CreateMedia = CREATE_MEDIA; + } + + private bool inArrange = false; + protected delegate Task ArrangeDelegate(); + protected async Task Arrange(ArrangeDelegate arrange) + { + if (inArrange) + return; + + inArrange = true; + try + { + CreateMedia = false; + try + { + // PatchRegister(); // No longer needed - seed data is correct + PurgeMDR(); + PurgeMDHIdentityServer(); + PurgeMDHEnergyIdentityServer(); + PurgeMDH(); + PurgeMDHE(); + await arrange(); + } + finally + { + CreateMedia = CREATE_MEDIA; + } + } + finally + { + inArrange = false; + } + } + + private bool inCleanup = false; + protected delegate Task CleanupDelegate(IPage page); + protected async Task CleanupAsync(CleanupDelegate cleanup) + { + if (inArrange) // shouldn't cleanup if arranging + return; + + if (inCleanup) + return; + + inCleanup = true; + try + { + // Setup Playwright + using var playwright = await Playwright.CreateAsync(); + + // Setup browser + await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions + { + SlowMo = 250, +#if TEST_DEBUG_MODE + Headless = false, + Timeout = 5000 // DEBUG - 5 seconds +#endif + }); + + // Setup browser context + var context = await browser.NewContextAsync(new BrowserNewContextOptions + { + IgnoreHTTPSErrors = true, + RecordVideoDir = null, + ViewportSize = new ViewportSize + { + Width = 1200, + Height = 1600 + } + }); + + try + { + var page = await context.NewPageAsync(); + page.Close += async (_, page) => + { + }; + + using (new AssertionScope()) + { + page.SetDefaultTimeout(TEST_TIMEOUT); + await cleanup(page); + } + } + finally + { + await context.CloseAsync(); + await browser.CloseAsync(); + } + } + finally + { + inCleanup = false; + } + } + protected delegate Task TestDelegate(IPage page); protected async Task TestAsync(string testName, TestDelegate testDelegate) //, bool? CreateMedia = true) { @@ -102,13 +260,13 @@ static void DeleteFile(string filename) IgnoreHTTPSErrors = true, RecordVideoDir = CreateMedia == true ? $"{MEDIAFOLDER}" : null, -#if !TEST_DEBUG_MODE + //#if !TEST_DEBUG_MODE ViewportSize = new ViewportSize { Width = 1200, Height = 1600 } -#endif + //#endif }); string? videoPath = null; @@ -131,6 +289,7 @@ static void DeleteFile(string filename) using (new AssertionScope()) { + page.SetDefaultTimeout(TEST_TIMEOUT); await testDelegate(page); } } @@ -233,5 +392,141 @@ protected static void Assert_Json2(string? actualJson, (string name, string? val } } } + + public static void PatchRegister() + { + using var connection = new SqlConnection(BaseTest.REGISTER_CONNECTIONSTRING); + connection.Open(); + + // mock-data-recipient + using var updateCommand = new SqlCommand($@" + update + softwareproduct + set + recipientbaseuri = 'https://{BaseTest.HOSTNAME_DATARECIPIENT}:9001', + revocationuri = 'https://{BaseTest.HOSTNAME_DATARECIPIENT}:9001/revocation', + redirecturis = 'https://{BaseTest.HOSTNAME_DATARECIPIENT}:9001/consent/callback', + jwksuri = 'https://{BaseTest.HOSTNAME_DATARECIPIENT}:9001/jwks' + where + softwareproductid = '{BaseTest.DR_SOFTWAREPRODUCTID}'", + connection); + updateCommand.ExecuteNonQuery(); + + // mock-data-holder + using var updateCommand2 = new SqlCommand($@" + update + endpoint + set + publicbaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER}:8000', + resourcebaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER}:8002', + infosecbaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER}:8001' + where + brandid = '{BaseTest.DH_BRANDID}'", + connection); + updateCommand2.ExecuteNonQuery(); + + // mock-data-holder-energy + using var updateCommand3 = new SqlCommand($@" + update + endpoint + set + publicbaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER_ENERGY}:8100', + resourcebaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER_ENERGY}:8102', + infosecbaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER_ENERGY}:8101' + where + brandid = '{BaseTest.DH_BRANDID_ENERGY}'", + connection); + updateCommand3.ExecuteNonQuery(); + } + + static void Purge(SqlConnection connection, string table) + { + // Delete all rows from table + using var deleteCommand = new SqlCommand($"delete from {table}", connection); + deleteCommand.ExecuteNonQuery(); + + // Check all rows deleted + using var selectCommand = new SqlCommand($"select count(*) from {table}", connection); + var count = Convert.ToInt32(selectCommand.ExecuteScalar()); + if (count != 0) + { + throw new Exception($"Error purging {table}"); + } + } + + public static void PurgeMDR() + { + using var mdrConnection = new SqlConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); + mdrConnection.Open(); + + Purge(mdrConnection, "CdrArrangement"); + Purge(mdrConnection, "DataHolderBrand"); + Purge(mdrConnection, "Registration"); + } + + public static void PurgeMDH() + { + // using var mdhConnection = new SqlConnection(BaseTest.DATAHOLDER_CONNECTIONSTRING); + // mdhConnection.Open(); + // Purge(mdhConnection, "Brand"); + // Purge(mdhConnection, "SoftwareProduct"); + } + + public static void PurgeMDHE() + { + // using var mdheConnection = new SqlConnection(BaseTest.DATAHOLDER_ENERGY_CONNECTIONSTRING); + // mdheConnection.Open(); + // Purge(mdheConnection, "Brand"); + // Purge(mdheConnection, "SoftwareProduct"); + } + + // public static void PurgeMDR_CDRArrangements() + // { + // using var mdrConnection = new SqlConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); + // mdrConnection.Open(); + // Purge(mdrConnection, "CdrArrangement"); + // } + + private static void PurgeIdentityServer(string connectionString) + { + using var identityServerConnection = new SqlConnection(connectionString); + identityServerConnection.Open(); + + // Purge(identityServerConnection, "ApiResourceClaims"); + // Purge(identityServerConnection, "ApiResourceProperties"); + // Purge(identityServerConnection, "ApiResources"); + // Purge(identityServerConnection, "ApiResourceScopes"); + // Purge(identityServerConnection, "ApiResourceSecrets"); + // Purge(identityServerConnection, "ApiScopeClaims"); + // Purge(identityServerConnection, "ApiScopeProperties"); + // Purge(identityServerConnection, "ApiScopes"); + Purge(identityServerConnection, "ClientClaims"); + Purge(identityServerConnection, "ClientCorsOrigins"); + Purge(identityServerConnection, "ClientGrantTypes"); + Purge(identityServerConnection, "ClientIdPRestrictions"); + Purge(identityServerConnection, "ClientPostLogoutRedirectUris"); + Purge(identityServerConnection, "ClientProperties"); + Purge(identityServerConnection, "ClientRedirectUris"); + Purge(identityServerConnection, "Clients"); + Purge(identityServerConnection, "ClientScopes"); + Purge(identityServerConnection, "ClientSecrets"); + // Purge(identityServerConnection, "DeviceCodes"); + // Purge(identityServerConnection, "IdentityResourceClaims"); + // Purge(identityServerConnection, "IdentityResourceProperties"); + // Purge(identityServerConnection, "IdentityResources"); + Purge(identityServerConnection, "PersistedGrants"); + } + + public static void PurgeMDHIdentityServer() + { + PurgeIdentityServer(BaseTest.DATAHOLDER_IDENTITYSERVER_CONNECTIONSTRING); + } + + public static void PurgeMDHEnergyIdentityServer() + { + PurgeIdentityServer(BaseTest.DATAHOLDER_ENERGY_IDENTITYSERVER_CONNECTIONSTRING); + } } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/BaseTest_v2.cs b/Source/CDR.DataRecipient.E2ETests/BaseTest_v2.cs new file mode 100644 index 0000000..837ddb7 --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/BaseTest_v2.cs @@ -0,0 +1,552 @@ +// #define TEST_DEBUG_MODE // Run Playwright in non-headless mode for debugging purposes (ie show a browser) + +// In docker (Ubuntu container) Playwright will fail if running in non-headless mode, so we ensure TEST_DEBUG_MODE is undef'ed +#if !DEBUG +#undef TEST_DEBUG_MODE +#endif + +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using FluentAssertions; +using FluentAssertions.Execution; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Configuration; +using Microsoft.Playwright; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Xunit; + +#nullable enable + +namespace CDR.DataRecipient.E2ETests +{ + // Put all tests in same collection because we need them to run sequentially since some tests are mutating DB. + [Collection("E2ETests")] + [TestCaseOrderer("CDR.DataRecipient.E2ETests.XUnit.Orderers.AlphabeticalOrderer", "CDR.DataRecipient.E2ETests")] + [DisplayTestMethodName] + public class BaseTest_v2 + { + // Customers + public const string CUSTOMERID_BANKING = "jwilson"; + public const string CUSTOMERACCOUNTS_BANKING = "Personal Loan xxx-xxx xxxxx987,Transactions and Savings Account xxx-xxx xxxxx988"; + public const string CUSTOMERID_ENERGY = "mmoss"; + public const string CUSTOMERACCOUNTS_ENERGY = "'ELECTRICITY ACCOUNT','ELECTRICITY ACCOUNT 2',ELECTRICITY ACCOUNT 3,ELECTRICITY ACCOUNT 4,ELECTRICITY ACCOUNT 5,ELECTRICITY ACCOUNT 6,ELECTRICITY ACCOUNT 7,ELECTRICITY ACCOUNT 8,ELECTRICITY ACCOUNT 9,ELECTRICITY ACCOUNT 10,ELECTRICITY ACCOUNT 11,ELECTRICITY ACCOUNT 12,ELECTRICITY ACCOUNT 13,ELECTRICITY ACCOUNT 14,ELECTRICITY ACCOUNT 15,ELECTRICITY ACCOUNT 16,ELECTRICITY ACCOUNT 17,ELECTRICITY ACCOUNT 18,ELECTRICITY ACCOUNT 19,ELECTRICITY ACCOUNT 20,ELECTRICITY ACCOUNT 21"; + + // Data Holder + public const string DH_BRANDID = "804fc2fb-18a7-4235-9a49-2af393d18bc7"; + public const string DH_BRANDID_ENERGY = "cfcaf0df-401b-47f2-98af-94787289eca8"; // Mock Data Holder (Energy) + + // Data Recipient + public const string DR_BRANDID = "ffb1c8ba-279e-44d8-96f0-1bc34a6b436f"; + public const string DR_SOFTWAREPRODUCTID = "c6327f87-687a-4369-99a4-eaacd3bb8210"; + + // URLs + static public string REGISTER_MTLS_BaseURL => Configuration["MTLS_BaseURL"] + ?? throw new Exception($"{nameof(REGISTER_MTLS_BaseURL)} - configuration setting not found"); + + static public string REGISTER_IDENTITYSERVER_URL = REGISTER_MTLS_BaseURL + "/idp/connect/token"; + + // Client certificates + protected const string CERTIFICATE_FILENAME = "Certificates/client.pfx"; + protected const string CERTIFICATE_PASSWORD = "#M0ckDataRecipient#"; + + public const string JWT_CERTIFICATE_FILENAME = "Certificates/jwks.pfx"; + public const string JWT_CERTIFICATE_PASSWORD = "#M0ckDataRecipient#"; + + + public bool CreateMedia { get; set; } = true; + + // Test settings. + static public bool CREATE_MEDIA => Configuration.GetValue("CreateMedia", true); + static public int TEST_TIMEOUT => Configuration.GetValue("TestTimeout", 30000); + + // URL of the web UI + static public string WEB_URL => Configuration["Web_URL"] + ?? throw new Exception($"{nameof(WEB_URL)} - configuration setting not found"); + + // Hostnames + static public string HOSTNAME_REGISTER => Configuration["Hostnames:Register"] + ?? throw new Exception($"{nameof(HOSTNAME_REGISTER)} - configuration setting not found"); + static public string HOSTNAME_DATAHOLDER => Configuration["Hostnames:DataHolder"] + ?? throw new Exception($"{nameof(HOSTNAME_DATAHOLDER)} - configuration setting not found"); + static public string HOSTNAME_DATAHOLDER_ENERGY => Configuration["Hostnames:DataHolderEnergy"] + ?? throw new Exception($"{nameof(HOSTNAME_DATAHOLDER_ENERGY)} - configuration setting not found"); + static public string HOSTNAME_DATARECIPIENT => Configuration["Hostnames:DataRecipient"] + ?? throw new Exception($"{nameof(HOSTNAME_DATARECIPIENT)} - configuration setting not found"); + + // Connection strings + static public string DATAHOLDER_CONNECTIONSTRING => Configuration["ConnectionStrings:DataHolder"] + ?? throw new Exception($"{nameof(DATAHOLDER_CONNECTIONSTRING)} - configuration setting not found"); + static public string DATAHOLDER_ENERGY_CONNECTIONSTRING => Configuration["ConnectionStrings:DataHolderEnergy"] + ?? throw new Exception($"{nameof(DATAHOLDER_ENERGY_CONNECTIONSTRING)} - configuration setting not found"); + static public string DATAHOLDER_IDENTITYSERVER_CONNECTIONSTRING => Configuration["ConnectionStrings:DataHolderIdentityServer"] + ?? throw new Exception($"{nameof(DATAHOLDER_IDENTITYSERVER_CONNECTIONSTRING)} - configuration setting not found"); + static public string DATAHOLDER_ENERGY_IDENTITYSERVER_CONNECTIONSTRING => Configuration["ConnectionStrings:DataHolderEnergyIdentityServer"] + ?? throw new Exception($"{nameof(DATAHOLDER_ENERGY_IDENTITYSERVER_CONNECTIONSTRING)} - configuration setting not found"); + static public string REGISTER_CONNECTIONSTRING => Configuration["ConnectionStrings:Register"] + ?? throw new Exception($"{nameof(REGISTER_CONNECTIONSTRING)} - configuration setting not found"); + static public string DATARECIPIENT_CONNECTIONSTRING => Configuration["ConnectionStrings:DataRecipient"] + ?? throw new Exception($"{nameof(DATARECIPIENT_CONNECTIONSTRING)} - configuration setting not found"); + + // Media folder (for videos and screenshots) + static public string MEDIAFOLDER => Configuration["MediaFolder"] + ?? throw new Exception($"{nameof(MEDIAFOLDER)} - configuration setting not found"); + + // Dataholder - Access token lifetime seconds + static public string ACCESSTOKENLIFETIMESECONDS => Configuration["DataHolder:AccessTokenLifetimeSeconds"] + ?? throw new Exception($"{nameof(ACCESSTOKENLIFETIMESECONDS)} - configuration setting not found"); + + static private IConfigurationRoot? configuration; + static protected IConfigurationRoot Configuration + { + get + { + if (configuration == null) + { + configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", true) + .Build(); + } + + return configuration; + } + } + + protected BaseTest_v2() + { + // Default from config. + this.CreateMedia = CREATE_MEDIA; + } + + private bool inArrange = false; + protected delegate Task ArrangeDelegate(IPage page); + protected async Task ArrangeAsync(ArrangeDelegate arrange) + { + if (inArrange) + return; + + inArrange = true; + try + { + // Setup Playwright + using var playwright = await Playwright.CreateAsync(); + + // Setup browser + await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions + { + SlowMo = 250, +#if TEST_DEBUG_MODE + Headless = false, + Timeout = 5000 // DEBUG - 5 seconds +#endif + }); + + // Setup browser context + var context = await browser.NewContextAsync(new BrowserNewContextOptions + { + IgnoreHTTPSErrors = true, + RecordVideoDir = null, + ViewportSize = new ViewportSize + { + Width = 1200, + Height = 1600 + } + }); + + try + { + var page = await context.NewPageAsync(); + page.Close += async (_, page) => + { + }; + + using (new AssertionScope()) + { + page.SetDefaultTimeout(TEST_TIMEOUT); + await arrange(page); + } + } + finally + { + await context.CloseAsync(); + await browser.CloseAsync(); + } + } + finally + { + inArrange = false; + } + } + + private bool inCleanup = false; + protected delegate Task CleanupDelegate(IPage page); + protected async Task CleanupAsync(CleanupDelegate cleanup) + { + if (inArrange || inCleanup) + return; + + inCleanup = true; + try + { + // Setup Playwright + using var playwright = await Playwright.CreateAsync(); + + // Setup browser + await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions + { + SlowMo = 250, +#if TEST_DEBUG_MODE + Headless = false, + Timeout = 5000 // DEBUG - 5 seconds +#endif + }); + + // Setup browser context + var context = await browser.NewContextAsync(new BrowserNewContextOptions + { + IgnoreHTTPSErrors = true, + RecordVideoDir = null, + ViewportSize = new ViewportSize + { + Width = 1200, + Height = 1600 + } + }); + + try + { + var page = await context.NewPageAsync(); + page.Close += async (_, page) => + { + }; + + using (new AssertionScope()) + { + page.SetDefaultTimeout(TEST_TIMEOUT); + await cleanup(page); + } + } + finally + { + await context.CloseAsync(); + await browser.CloseAsync(); + } + } + finally + { + inCleanup = false; + } + } + + protected delegate Task TestDelegate(IPage page); + protected async Task TestAsync(string testName, TestDelegate testDelegate) //, bool? CreateMedia = true) + { + _testName = testName; + + static void DeleteFile(string filename) + { + if (File.Exists(filename)) + { + File.Delete(filename); + } + } + + if (CreateMedia == true) + { + // Remove video/screens if they exist + DeleteFile($"{MEDIAFOLDER}/{testName}.webm"); + DeleteFile($"{MEDIAFOLDER}/{testName}.png"); + DeleteFile($"{MEDIAFOLDER}/{testName}-exception.png"); + } + + // Setup Playwright + using var playwright = await Playwright.CreateAsync(); + + // Setup browser + await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions + { + SlowMo = 250, +#if TEST_DEBUG_MODE + Headless = false, + Timeout = 5000 // DEBUG - 5 seconds +#endif + }); + + // Setup browser context + var context = await browser.NewContextAsync(new BrowserNewContextOptions + { + IgnoreHTTPSErrors = true, + RecordVideoDir = CreateMedia == true ? $"{MEDIAFOLDER}" : null, + + //#if !TEST_DEBUG_MODE + ViewportSize = new ViewportSize + { + Width = 1200, + Height = 1600 + } + //#endif + }); + + string? videoPath = null; + try + { + var page = await context.NewPageAsync(); + try + { + page.Close += async (_, page) => + { + // Page is closed, so save videoPath + if (CreateMedia == true) + { + if (page.Video != null) + { + videoPath = await page.Video.PathAsync(); + } + } + }; + + using (new AssertionScope()) + { + page.SetDefaultTimeout(TEST_TIMEOUT); + await testDelegate(page); + } + } + finally + { + // Save a screenshot + if (CreateMedia == true) + { + await ScreenshotAsync(page, ""); + } + } + } + finally + { + // Wait 1 second so that video captures final state of page + await Task.Delay(1000); + + await context.CloseAsync(); + + // Rename video file + if (CreateMedia == true) + { + if (videoPath != null) + { + File.Move(videoPath, $"{MEDIAFOLDER}/{testName}.webm"); + } + } + + await browser.CloseAsync(); + } + } + + private string? _testName; + public async Task ScreenshotAsync(IPage page, string name) + { + await page.ScreenshotAsync(new PageScreenshotOptions { Path = $"{MEDIAFOLDER}/{_testName}{name}.png" }); + } + + protected static string? StripJsonProperty(string? json, string propertyName) + { + if (String.IsNullOrEmpty(json)) + return json; + + return Regex.Replace(json, @$"""{propertyName}"".*", ""); + } + + protected static void Assert_Json(string? expectedJson, string? actualJson) + { + static object? Deserialize(string json) + { + try { return JsonConvert.DeserializeObject(json); } + catch { return null; } + } + + static bool JsonCompare(string json, string jsonToCompare) + { + var jsonToken = JToken.Parse(json); + var jsonToCompareToken = JToken.Parse(jsonToCompare); + return JToken.DeepEquals(jsonToken, jsonToCompareToken); + } + + expectedJson.Should().NotBeNullOrEmpty(); + actualJson.Should().NotBeNullOrEmpty(expectedJson == null ? "" : $"expected {expectedJson}"); + + if (string.IsNullOrEmpty(expectedJson) || string.IsNullOrEmpty(actualJson)) + return; + + object? expectedObject = Deserialize(expectedJson); + expectedObject.Should().NotBeNull($"Error deserializing expected json - '{expectedJson}'"); + + object? actualObject = Deserialize(actualJson); + actualObject.Should().NotBeNull($"Error deserializing actual json - '{actualJson}'"); + + var expectedJsonNormalised = JsonConvert.SerializeObject(expectedObject); + var actualJsonNormalised = JsonConvert.SerializeObject(actualObject); + + JsonCompare(actualJson, expectedJson).Should().BeTrue( + $"\r\nExpected json:\r\n{expectedJsonNormalised}\r\nActual Json:\r\n{actualJsonNormalised}\r\n" + ); + } + + protected const string ASSERT_JSON2_ANYVALUE = "***ANYVALUE***"; + protected static void Assert_Json2(string? actualJson, (string name, string? value)[] expected) + { + actualJson.Should().NotBeNullOrEmpty(); + if (actualJson == null) + return; + + var root = JToken.Parse(actualJson); + + foreach ((var name, var value) in expected) + { + // Assert that json property exists + root[name].Should().NotBeNull($"Missing property '{name}'"); + + // Assert that value matches + if (value != ASSERT_JSON2_ANYVALUE) + { + root.Value(name).Should().Be(value, $"Property '{name}' should be '{value}'"); + } + } + } + + public static void PatchRegister() + { + using var connection = new SqlConnection(BaseTest_v2.REGISTER_CONNECTIONSTRING); + connection.Open(); + + // mock-data-recipient + using var updateCommand = new SqlCommand($@" + update + softwareproduct + set + recipientbaseuri = 'https://{BaseTest_v2.HOSTNAME_DATARECIPIENT}:9001', + revocationuri = 'https://{BaseTest_v2.HOSTNAME_DATARECIPIENT}:9001/revocation', + redirecturis = 'https://{BaseTest_v2.HOSTNAME_DATARECIPIENT}:9001/consent/callback', + jwksuri = 'https://{BaseTest_v2.HOSTNAME_DATARECIPIENT}:9001/jwks' + where + softwareproductid = '{BaseTest_v2.DR_SOFTWAREPRODUCTID}'", + connection); + updateCommand.ExecuteNonQuery(); + + // mock-data-holder + using var updateCommand2 = new SqlCommand($@" + update + endpoint + set + publicbaseuri = 'https://{BaseTest_v2.HOSTNAME_DATAHOLDER}:8000', + resourcebaseuri = 'https://{BaseTest_v2.HOSTNAME_DATAHOLDER}:8002', + infosecbaseuri = 'https://{BaseTest_v2.HOSTNAME_DATAHOLDER}:8001' + where + brandid = '{BaseTest_v2.DH_BRANDID}'", + connection); + updateCommand2.ExecuteNonQuery(); + + // mock-data-holder-energy + using var updateCommand3 = new SqlCommand($@" + update + endpoint + set + publicbaseuri = 'https://{BaseTest_v2.HOSTNAME_DATAHOLDER_ENERGY}:8100', + resourcebaseuri = 'https://{BaseTest_v2.HOSTNAME_DATAHOLDER_ENERGY}:8102', + infosecbaseuri = 'https://{BaseTest_v2.HOSTNAME_DATAHOLDER_ENERGY}:8101' + where + brandid = '{BaseTest_v2.DH_BRANDID_ENERGY}'", + connection); + updateCommand3.ExecuteNonQuery(); + } + + static void Purge(SqlConnection connection, string table) + { + // Delete all rows from table + using var deleteCommand = new SqlCommand($"delete from {table}", connection); + deleteCommand.ExecuteNonQuery(); + + // Check all rows deleted + using var selectCommand = new SqlCommand($"select count(*) from {table}", connection); + var count = Convert.ToInt32(selectCommand.ExecuteScalar()); + if (count != 0) + { + throw new Exception($"Error purging {table}"); + } + } + + public static void PurgeMDR() + { + using var mdrConnection = new SqlConnection(BaseTest_v2.DATARECIPIENT_CONNECTIONSTRING); + mdrConnection.Open(); + + Purge(mdrConnection, "CdrArrangement"); + Purge(mdrConnection, "DataHolderBrand"); + Purge(mdrConnection, "Registration"); + } + + public static void PurgeMDH() + { + // using var mdhConnection = new SqlConnection(BaseTest_v2.DATAHOLDER_CONNECTIONSTRING); + // mdhConnection.Open(); + // Purge(mdhConnection, "Brand"); + // Purge(mdhConnection, "SoftwareProduct"); + } + + public static void PurgeMDHE() + { + // using var mdheConnection = new SqlConnection(BaseTest_v2.DATAHOLDER_ENERGY_CONNECTIONSTRING); + // mdheConnection.Open(); + // Purge(mdheConnection, "Brand"); + // Purge(mdheConnection, "SoftwareProduct"); + } + + // public static void PurgeMDR_CDRArrangements() + // { + // using var mdrConnection = new SqlConnection(BaseTest_v2.DATARECIPIENT_CONNECTIONSTRING); + // mdrConnection.Open(); + // Purge(mdrConnection, "CdrArrangement"); + // } + + private static void PurgeIdentityServer(string connectionString) + { + using var identityServerConnection = new SqlConnection(connectionString); + identityServerConnection.Open(); + + // Purge(identityServerConnection, "ApiResourceClaims"); + // Purge(identityServerConnection, "ApiResourceProperties"); + // Purge(identityServerConnection, "ApiResources"); + // Purge(identityServerConnection, "ApiResourceScopes"); + // Purge(identityServerConnection, "ApiResourceSecrets"); + // Purge(identityServerConnection, "ApiScopeClaims"); + // Purge(identityServerConnection, "ApiScopeProperties"); + // Purge(identityServerConnection, "ApiScopes"); + Purge(identityServerConnection, "ClientClaims"); + Purge(identityServerConnection, "ClientCorsOrigins"); + Purge(identityServerConnection, "ClientGrantTypes"); + Purge(identityServerConnection, "ClientIdPRestrictions"); + Purge(identityServerConnection, "ClientPostLogoutRedirectUris"); + Purge(identityServerConnection, "ClientProperties"); + Purge(identityServerConnection, "ClientRedirectUris"); + Purge(identityServerConnection, "Clients"); + Purge(identityServerConnection, "ClientScopes"); + Purge(identityServerConnection, "ClientSecrets"); + // Purge(identityServerConnection, "DeviceCodes"); + // Purge(identityServerConnection, "IdentityResourceClaims"); + // Purge(identityServerConnection, "IdentityResourceProperties"); + // Purge(identityServerConnection, "IdentityResources"); + Purge(identityServerConnection, "PersistedGrants"); + } + + public static void PurgeMDHIdentityServer() + { + PurgeIdentityServer(BaseTest_v2.DATAHOLDER_IDENTITYSERVER_CONNECTIONSTRING); + } + + public static void PurgeMDHEnergyIdentityServer() + { + PurgeIdentityServer(BaseTest_v2.DATAHOLDER_ENERGY_IDENTITYSERVER_CONNECTIONSTRING); + } + } +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/CDR.DataRecipient.E2ETests.csproj b/Source/CDR.DataRecipient.E2ETests/CDR.DataRecipient.E2ETests.csproj index 16d5518..569c0ab 100644 --- a/Source/CDR.DataRecipient.E2ETests/CDR.DataRecipient.E2ETests.csproj +++ b/Source/CDR.DataRecipient.E2ETests/CDR.DataRecipient.E2ETests.csproj @@ -1,33 +1,57 @@ - net5.0 + net6.0 false + 0.2.0 + 0.2.0 + 0.2.0 + + + + + + + Always + + + Always + Always - + Always - - - - - + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all + + + + + + + + Always + + diff --git a/Source/CDR.DataRecipient.E2ETests/Certificates/client.pfx b/Source/CDR.DataRecipient.E2ETests/Certificates/client.pfx new file mode 100644 index 0000000..85e022e Binary files /dev/null and b/Source/CDR.DataRecipient.E2ETests/Certificates/client.pfx differ diff --git a/Source/CDR.DataRecipient.E2ETests/DisplayTestMethodNameAttribute.cs b/Source/CDR.DataRecipient.E2ETests/DisplayTestMethodNameAttribute.cs new file mode 100644 index 0000000..0d28241 --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/DisplayTestMethodNameAttribute.cs @@ -0,0 +1,22 @@ +using System; +using System.Reflection; +using Xunit.Sdk; + +#nullable enable + +namespace CDR.DataRecipient.E2ETests +{ + class DisplayTestMethodNameAttribute : BeforeAfterTestAttribute + { + static int count = 0; + + public override void Before(MethodInfo methodUnderTest) + { + Console.WriteLine($"Test #{++count} - {methodUnderTest.DeclaringType?.Name}.{methodUnderTest.Name}"); + } + + public override void After(MethodInfo methodUnderTest) + { + } + } +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/Fixtures/TestFixture.cs b/Source/CDR.DataRecipient.E2ETests/Fixtures/TestFixture.cs new file mode 100644 index 0000000..cb9cd59 --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/Fixtures/TestFixture.cs @@ -0,0 +1,26 @@ +using Microsoft.Data.SqlClient; +using System; +using System.Threading.Tasks; +using Xunit; + +#nullable enable + +namespace CDR.DataRecipient.E2ETests +{ + public class TestFixture : IAsyncLifetime + { + public Task InitializeAsync() + { + // Ensure that Playwright has been fully installed. + Microsoft.Playwright.Program.Main(new string[] { "install" }); + Microsoft.Playwright.Program.Main(new string[] { "install-deps" }); + + return Task.CompletedTask; + } + + public Task DisposeAsync() + { + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/Infrastructure/AccessToken.cs b/Source/CDR.DataRecipient.E2ETests/Infrastructure/AccessToken.cs new file mode 100644 index 0000000..232e275 --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/Infrastructure/AccessToken.cs @@ -0,0 +1,140 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using CDR.DataRecipient.IntegrationTests.Infrastructure; + +#nullable enable + +namespace CDR.DataRecipient.E2ETests.Infrastructure +{ + public class AccessToken + { + private static readonly string IDENTITYSERVER_URL = BaseTest_v2.REGISTER_IDENTITYSERVER_URL; + private static readonly string AUDIENCE = IDENTITYSERVER_URL; + private const string SCOPE = "cdr-register:bank:read"; + private const string GRANT_TYPE = "client_credentials"; + private const string CLIENT_ID = "c6327f87-687a-4369-99a4-eaacd3bb8210"; + private const string CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; + private const string ISSUER = CLIENT_ID; + + /// + /// Filename of certificate to use. + /// If null then no certificate will be attached to the request. + /// + public string? CertificateFilename { get; set; } + + /// + /// Password for certificate. + /// If null then no certificate password will be set. + /// + public string? CertificatePassword { get; set; } + + public string Issuer { get; set; } = ISSUER; + public string Audience { get; set; } = AUDIENCE; + public string Scope { get; set; } = SCOPE; + public string GrantType { get; set; } = GRANT_TYPE; + public string ClientId { get; set; } = CLIENT_ID; + public string ClientAssertionType { get; set; } = CLIENT_ASSERTION_TYPE; + + /// + /// Get HttpRequestMessage for access token request + /// + private static HttpRequestMessage CreateAccessTokenRequest( + string? certificateFilename, string? certificatePassword, + string issuer, string audience, + string scope, string grant_type, string client_id, string client_assertion_type) + { + static string BuildContent(string scope, string grant_type, string client_id, string client_assertion_type, string client_assertion) + { + var kvp = new KeyValuePairBuilder(); + + if (scope != null) + { + kvp.Add("scope", scope); + } + + if (grant_type != null) + { + kvp.Add("grant_type", grant_type); + } + + if (client_id != null) + { + kvp.Add("client_id", client_id); + } + + if (client_assertion_type != null) + { + kvp.Add("client_assertion_type", client_assertion_type); + } + + if (client_assertion != null) + { + kvp.Add("client_assertion", client_assertion); + } + + return kvp.Value; + } + + var tokenizer = new PrivateKeyJwt(certificateFilename, certificatePassword); + var client_assertion = tokenizer.Generate(issuer, audience); + + var request = new HttpRequestMessage(HttpMethod.Post, IDENTITYSERVER_URL) + { + Content = new StringContent( + BuildContent(scope, grant_type, client_id, client_assertion_type, client_assertion), + Encoding.UTF8, + "application/json") + }; + + request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); + + return request; + } + + /// + /// Get an access token from Identity Server + /// + public async Task GetAsync() + { + // Create ClientHandler + var _clientHandler = new HttpClientHandler(); + _clientHandler.ServerCertificateCustomValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; + + // Attach client certificate to handler + if (CertificateFilename != null) + { + var clientCertificate = new X509Certificate2(CertificateFilename, CertificatePassword, X509KeyStorageFlags.Exportable); + _clientHandler.ClientCertificates.Add(clientCertificate); + } + + // Create HttpClient + using var client = new HttpClient(_clientHandler); + + // Create an access token request + var request = CreateAccessTokenRequest( + CertificateFilename, CertificatePassword, + Issuer, Audience, + Scope, GrantType, ClientId, ClientAssertionType); + + // Request the access token + var response = await client.SendAsync(request); + + if (response.StatusCode != HttpStatusCode.OK) + { + throw new Exception($"{nameof(AccessToken)}.{nameof(GetAsync)} - Error getting access token"); + } + + // Deserialize the access token from the response + var accessToken = JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync()); + + // And return the access token + return accessToken?.access_token; + } + } +} diff --git a/Source/CDR.DataRecipient.E2ETests/TestFixture.cs b/Source/CDR.DataRecipient.E2ETests/TestFixture.cs deleted file mode 100644 index 5b40277..0000000 --- a/Source/CDR.DataRecipient.E2ETests/TestFixture.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Data.Sqlite; -using Xunit; - -#nullable enable - -namespace CDR.DataRecipient.E2ETests -{ - public class TestFixture : IAsyncLifetime - { - public static void PatchRegister() - { - using var connection = new SqliteConnection(BaseTest.REGISTER_CONNECTIONSTRING); - connection.Open(); - - using var updateCommand = new SqliteCommand(@" - update - softwareproduct - set - recipientbaseuri = 'https://localhost:9001', - revocationuri = 'https://localhost:9001/revocation', - redirecturis = 'https://localhost:9001/consent/callback', - jwksuri = 'https://localhost:9001/jwks' - where - softwareproductid = 'C6327F87-687A-4369-99A4-EAACD3BB8210'", - connection); - updateCommand.ExecuteNonQuery(); - - using var updateCommand2 = new SqliteCommand(@" - update - endpoint - set - publicbaseuri = 'https://localhost:8000', - resourcebaseuri = 'https://localhost:8002', - infosecbaseuri = 'https://localhost:8001' - where - brandid = '804FC2FB-18A7-4235-9A49-2AF393D18BC7'", - connection); - updateCommand2.ExecuteNonQuery(); - } - - static void Purge(SqliteConnection connection, string table) - { - // Delete all rows from table - using var deleteCommand = new SqliteCommand($"delete from {table}", connection); - deleteCommand.ExecuteNonQuery(); - - // Check all rows deleted - using var selectCommand = new SqliteCommand($"select count(*) from {table}", connection); - var count = Convert.ToInt32(selectCommand.ExecuteScalar()); - if (count != 0) - { - throw new Exception($"Error purging {table}"); - } - } - - public static void PurgeMDR() - { - using var mdrConnection = new SqliteConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); - mdrConnection.Open(); - - Purge(mdrConnection, "CdrArrangement"); - Purge(mdrConnection, "DataHolderBrand"); - Purge(mdrConnection, "Registration"); - } - - public static void PurgeMDR_CDRArrangements() - { - using var mdrConnection = new SqliteConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); - mdrConnection.Open(); - - Purge(mdrConnection, "CdrArrangement"); - } - - // static void PurgeMDRArrangements() - // { - // using var mdrConnection = new SqliteConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); - // mdrConnection.Open(); - - // Purge(mdrConnection, "CdrArrangement"); - // } - - public static void PurgeMDHIdentityServer() - { - using var mdhIdentityServerConnection = new SqliteConnection(BaseTest.DATAHOLDER_IDENTITYSERVER_CONNECTIONSTRING); - mdhIdentityServerConnection.Open(); - - // Purge(mdhIdentityServerConnection, "ApiResourceClaims"); - // Purge(mdhIdentityServerConnection, "ApiResourceProperties"); - // Purge(mdhIdentityServerConnection, "ApiResources"); - // Purge(mdhIdentityServerConnection, "ApiResourceScopes"); - // Purge(mdhIdentityServerConnection, "ApiResourceSecrets"); - // Purge(mdhIdentityServerConnection, "ApiScopeClaims"); - // Purge(mdhIdentityServerConnection, "ApiScopeProperties"); - // Purge(mdhIdentityServerConnection, "ApiScopes"); - Purge(mdhIdentityServerConnection, "ClientClaims"); - Purge(mdhIdentityServerConnection, "ClientCorsOrigins"); - Purge(mdhIdentityServerConnection, "ClientGrantTypes"); - Purge(mdhIdentityServerConnection, "ClientIdPRestrictions"); - Purge(mdhIdentityServerConnection, "ClientPostLogoutRedirectUris"); - Purge(mdhIdentityServerConnection, "ClientProperties"); - Purge(mdhIdentityServerConnection, "ClientRedirectUris"); - Purge(mdhIdentityServerConnection, "Clients"); - Purge(mdhIdentityServerConnection, "ClientScopes"); - Purge(mdhIdentityServerConnection, "ClientSecrets"); - // Purge(mdhIdentityServerConnection, "DeviceCodes"); - // Purge(mdhIdentityServerConnection, "IdentityResourceClaims"); - // Purge(mdhIdentityServerConnection, "IdentityResourceProperties"); - // Purge(mdhIdentityServerConnection, "IdentityResources"); - Purge(mdhIdentityServerConnection, "PersistedGrants"); - } - - public Task InitializeAsync() - { - // DEBUG - comment out these lines - only for debugging - // PatchRegister(); - // PurgeMDR(); - // PurgeMDRArrangements(); - // PurgeMDHIdentityServer(); - - return Task.CompletedTask; - } - - public Task DisposeAsync() - { - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/TestPlaywrightInstallation.cs b/Source/CDR.DataRecipient.E2ETests/TestPlaywrightInstallation.cs deleted file mode 100644 index 862edb4..0000000 --- a/Source/CDR.DataRecipient.E2ETests/TestPlaywrightInstallation.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Threading.Tasks; -using FluentAssertions; -using Microsoft.Data.Sqlite; -using Xunit; - -#nullable enable - -namespace CDR.DataRecipient.E2ETests -{ -#if DISABLED - public class TestPlaywrightInstallation : BaseTest - { - [Fact] - public static async Task ShouldDisplayGoogleHomePage() - { - await TestAsync($"{nameof(TestPlaywrightInstallation)} - {nameof(ShouldDisplayGoogleHomePage)}", async (page) => - { - // Act - Goto Google.com - await page.GotoAsync("https://www.google.com"); - }); - } - } -#endif -} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/US23863_MDR_E2ETests.cs b/Source/CDR.DataRecipient.E2ETests/US23863_MDR_E2ETests.cs index 050aa70..70625da 100644 --- a/Source/CDR.DataRecipient.E2ETests/US23863_MDR_E2ETests.cs +++ b/Source/CDR.DataRecipient.E2ETests/US23863_MDR_E2ETests.cs @@ -1,8 +1,11 @@ -using System; -using System.Threading.Tasks; +#undef DEPRECATED // instead see US23863_MDR_E2ETests_v2 +#if DEPRECATED + using FluentAssertions; -using Microsoft.Data.Sqlite; +using Microsoft.Data.SqlClient; using Microsoft.Playwright; +using System; +using System.Threading.Tasks; using Xunit; #nullable enable @@ -11,6 +14,9 @@ namespace CDR.DataRecipient.E2ETests { public class US23863_MDR_E2ETests : BaseTest, IClassFixture { + private const string SWAGGER_BANKING_IFRAME = "cds-banking/index.html"; + private const string SWAGGER_ENERGY_IFRAME = "cds-energy/index.html"; + private const string SHARING_DURATION = "100000"; // Pre-generated ID Token used in IDTokenhelper test @@ -29,41 +35,12 @@ public class US23863_MDR_E2ETests : BaseTest, IClassFixture "TB9U3T-pxeWnjaefeLxXDlQx7ZRPIni7Yf7sB3u4IoxfUNuORHL9OP1d_fljD_pd65xZEY-weNGJ8NhlFeMzf_e288dg44PD2xzkk5oAsh_qdn8HKV8PeBTaiUywYvQiQM3HGGJ6kd3TeB2UYmLFlCwsjONt_qJ7w" + "dJ9KgyjWN6ypuCrbCZ9TGq6i0o3HjH6tNup6ltnYfquW1FPmyIeB_TEQ3GLsxJSAauomwJ9PljuEJlhZsh7Cllc8ack7R47UHbYXAYTR2VVt11PsAWrdeCoAQpjqQ.S6AhwkvWKyJ7Jz3nmp_PJg"; - private bool inArrange = false; - private delegate Task ArrangeDelegate(); - private async Task Arrange(ArrangeDelegate arrange) - { - if (inArrange) - return; - - inArrange = true; - try - { - CreateMedia = false; - try - { - TestFixture.PatchRegister(); - TestFixture.PurgeMDR(); - TestFixture.PurgeMDHIdentityServer(); - await arrange(); - } - finally - { - CreateMedia = true; - } - } - finally - { - inArrange = true; - } - } - static string GetClientId() { - using var mdrConnection = new SqliteConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); + using var mdrConnection = new SqlConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); mdrConnection.Open(); - using var selectCommand = new SqliteCommand($"select clientid from registration", mdrConnection); + using var selectCommand = new SqlCommand($"select clientid from registration", mdrConnection); string? clientId = Convert.ToString(selectCommand.ExecuteScalar()); if (String.IsNullOrEmpty(clientId)) @@ -83,11 +60,10 @@ public class ConsentAndAuthorisationResponse public string? CDRArrangementID { get; init; } } - // static async Task<(string? idToken, string? accessToken, string? refreshToken, string? scope, string? cdrArrangementId)> ConsentAndAuthorisation(IPage page) - static async Task ConsentAndAuthorisation(IPage page) + static async Task ConsentAndAuthorisation(IPage page, string customerId = CUSTOMERID_BANKING, string customerAccounts = CUSTOMERACCOUNTS_BANKING) { // Act - Enter Customer ID - await page.Locator("[placeholder=\"Your Customer ID\"]").FillAsync("jwilson"); + await page.Locator("[placeholder=\"Your Customer ID\"]").FillAsync(customerId); await page.Locator("text=Continue").ClickAsync(); // Act - Wait for OTP, then enter it, and click Continue @@ -95,8 +71,13 @@ static async Task ConsentAndAuthorisation(IPage await page.Locator("[placeholder=\"Enter 6 digit One Time Password\"]").FillAsync("000789"); await page.Locator("text=Continue").ClickAsync(); - // Act - select Personal Loan account, click Continue and I confirm - await page.Locator("text=Personal Loan xxx-xxx xxxxx987").ClickAsync(); + // Act - Select accounts + foreach (var customerAccount in customerAccounts.Split(',')) + { + await page.Locator($"text={customerAccount}").ClickAsync(); + } + + // Act - Click Continue and I confirm await page.Locator("text=Continue").ClickAsync(); await page.Locator("text=I Confirm").ClickAsync(); @@ -194,7 +175,8 @@ await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC01_HomePage)}", asy await page.Locator("a >> text=Dynamic Client Registration").TextContentAsync(); await page.Locator("a >> text=Consent and Authorisation").TextContentAsync(); await page.Locator("a >> text=Consents").TextContentAsync(); - await page.Locator("a >> text=Consumer Data Sharing").TextContentAsync(); + await page.Locator("a >> text=Consumer Data Sharing - Banking").TextContentAsync(); + await page.Locator("a >> text=Consumer Data Sharing - Energy").TextContentAsync(); await page.Locator("a >> text=PAR").TextContentAsync(); await page.Locator("span >> text=Utilities").TextContentAsync(); await page.Locator("a >> text=ID Token Helper").TextContentAsync(); @@ -202,104 +184,255 @@ await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC01_HomePage)}", asy }); } - [Fact] - public async Task AC02_DiscoverDataHolders() + [Theory] + [InlineData("", "", null, "BadRequest - Bad Request")] + [InlineData("", "1", 32)] + [InlineData("", "2", null, "NotAcceptable - Not Acceptable")] + [InlineData("", "foo", null, "BadRequest - Bad Request")] + [InlineData("Banking", "", null, "BadRequest - Bad Request")] + [InlineData("Banking", "1", 30)] + [InlineData("Banking", "2", null, "NotAcceptable - Not Acceptable")] + [InlineData("Banking", "foo", null, "BadRequest - Bad Request")] + [InlineData("Energy", "", null, "BadRequest - Bad Request")] + [InlineData("Energy", "1", 2)] + [InlineData("Energy", "2", null, "NotAcceptable - Not Acceptable")] + [InlineData("Energy", "foo", null, "BadRequest - Bad Request")] + [InlineData("Telco", "", null, "BadRequest - Bad Request")] + [InlineData("Telco", "1", 0)] + [InlineData("Telco", "2", null, "NotAcceptable - Not Acceptable")] + [InlineData("Telco", "foo", null, "BadRequest - Bad Request")] + public async Task AC02_DiscoverDataHolders(string industry = "", string version = "1", int? expectedRecords = 32, string? expectedError = null) { await Arrange(async () => { }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC02_DiscoverDataHolders)}", async (page) => + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC02_DiscoverDataHolders)} - Industry={industry} - Version={version}", async (page) => { // Arrange - Goto home page, click menu button, check page loaded await page.GotoAsync(WEB_URL); await page.Locator("a >> text=Discover Data Holders").ClickAsync(); await page.Locator("h2 >> text=Discover Data Holders").TextContentAsync(); + // Set industry + if (String.IsNullOrEmpty(industry)) // Clear industry + await page.Locator("select[name=\"Industry\"]").SelectOptionAsync(new SelectOptionValue[] { }); + else + await page.Locator("select[name=\"Industry\"]").SelectOptionAsync(new[] { industry switch + { + // "" => "", // Doesn't work for clearing, use SelectOptionAsync(new SelectOptionValue[] { }) instead (see above) + "Banking" => "0", + "Energy" => "1", + "Telco" => "2", + _ => throw new ArgumentOutOfRangeException($"{nameof(industry)}") + }}); + + // Set version + await page.Locator("input[name=\"Version\"]").FillAsync(version); + // Act - Click Refresh button - await page.Locator(@"h5:has-text(""Refresh Data Holders"") ~ div.card-body >> input:has-text(""Refresh"")").ClickAsync(); ; + await page.Locator(@"h5:has-text(""Refresh Data Holders"") ~ div.card-body >> input:has-text(""Refresh"")").ClickAsync(); - // Assert - Check refresh was successful, card-footer should be showing OK - 30 data holder brands loaded - await page.Locator(@"h5:has-text(""Refresh Data Holders"") ~ div.card-footer >> text=OK - 30 data holder brands loaded").TextContentAsync(); + // Assert - Check refresh was successful + var footer = page.Locator(@"h5:has-text(""Refresh Data Holders"") ~ div.card-footer"); + var text = await footer.InnerTextAsync(); + if (expectedError != null) + { + text.Should().Be(expectedError); + } + else + { + text.Should().Be($"OK - {expectedRecords} data holder brands loaded."); + } }); } [Fact] - public async Task AC03_GetSSA() + public async Task AC02_DiscoverDataHolders_MultipleAttempts() + { + await Arrange(async () => { }); + + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC02_DiscoverDataHolders_MultipleAttempts)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Discover Data Holders").ClickAsync(); + await page.Locator("h2 >> text=Discover Data Holders").TextContentAsync(); + + // Act/Assert + await Test(page, "Banking", 30); + await Test(page, "Energy", 2); + await Test(page, "Banking", 30); + }); + + static async Task Test(IPage page, string industry, int expectedRecords) + { + // Arrange + if (String.IsNullOrEmpty(industry)) // Clear industry + await page.Locator("select[name=\"Industry\"]").SelectOptionAsync(new SelectOptionValue[] { }); + else + await page.Locator("select[name=\"Industry\"]").SelectOptionAsync(new[] { industry switch + { + "Banking" => "0", + "Energy" => "1", + "Telco" => "2", + _ => throw new ArgumentOutOfRangeException($"{nameof(industry)}") + }}); + + // Set version + await page.Locator("input[name=\"Version\"]").FillAsync("1"); + + // Act - Click Refresh button + await page.Locator(@"h5:has-text(""Refresh Data Holders"") ~ div.card-body >> input:has-text(""Refresh"")").ClickAsync(); + + // Assert - Check refresh was successful + var footer = page.Locator(@"h5:has-text(""Refresh Data Holders"") ~ div.card-footer"); + var text = await footer.InnerTextAsync(); + text.Should().Be($"OK - {expectedRecords} data holder brands loaded."); + } + } + + + [Theory] + [InlineData("", DR_BRANDID, DR_SOFTWAREPRODUCTID, "BadRequest")] + [InlineData("1", DR_BRANDID, DR_SOFTWAREPRODUCTID, "OK - SSA Generated")] + [InlineData("2", DR_BRANDID, DR_SOFTWAREPRODUCTID, "NotAcceptable")] + public async Task AC03_GetSSA(string version = "1", string drBrandId = DR_BRANDID, string drSoftwareProductId = DR_SOFTWAREPRODUCTID, string expectedMessage = "OK - SSA Generated") { await Arrange(async () => { await AC02_DiscoverDataHolders(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC03_GetSSA)}", async (page) => + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC03_GetSSA)} - Version={version} - DR_BrandId={drBrandId} - DR_SoftwareProductId={drSoftwareProductId}", async (page) => { // Arrange - Goto home page, click menu button, check page loaded await page.GotoAsync(WEB_URL); await page.Locator("a >> text=Get SSA").ClickAsync(); await page.Locator("h2 >> text=Get Software Statement Assertion").TextContentAsync(); + // Set version + await page.Locator("input[name=\"Version\"]").FillAsync(version); + // Set brandId + await page.Locator("input[name=\"BrandId\"]").FillAsync(drBrandId); + // Set softwareProductId + await page.Locator("input[name=\"SoftwareProductId\"]").FillAsync(drSoftwareProductId); + // Act - Click Refresh button await page.Locator(@"h5:has-text(""Get SSA"") ~ div.card-body >> input:has-text(""Get SSA"")").ClickAsync(); // Assert - Check refresh was successful, card-footer should be showing OK - SSA Generated - await page.Locator(@"h5:has-text(""Get SSA"") ~ div.card-footer >> text=OK - SSA Generated").TextContentAsync(); + var footer = page.Locator(@"h5:has-text(""Get SSA"") ~ div.card-footer"); + var text = await footer.InnerTextAsync(); + text.Should().StartWith(expectedMessage); }); } - [Fact] - public async Task AC04_DynamicClientRegistration() + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID)] + [InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID)] // Also test for Energy DH + public async Task AC04_DynamicClientRegistration(string dhBrandId = DH_BRANDID, string drBrandId = DR_BRANDID, string drSoftwareProductId = DR_SOFTWAREPRODUCTID) { await Arrange(async () => { await AC02_DiscoverDataHolders(); - await AC03_GetSSA(); + await AC03_GetSSA("1", drBrandId, drSoftwareProductId); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC04_DynamicClientRegistration)}", async (page) => + try { - // Arrange - Goto home page, click menu button, check page loaded - await page.GotoAsync(WEB_URL); - await page.Locator("a >> text=Dynamic Client Registration").ClickAsync(); - await page.Locator("h2 >> text=Dynamic Client Registration").TextContentAsync(); + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC04_DynamicClientRegistration)} - DH_BrandId={dhBrandId} - DR_BrandId={drBrandId} - DR_SoftwareProductId={drSoftwareProductId}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Dynamic Client Registration").ClickAsync(); + await page.Locator("h2 >> text=Dynamic Client Registration").TextContentAsync(); - // Act - Click Refresh button - await page.Locator(@"h5:has-text(""Create Client Registration"") ~ div.card-body >> input:has-text(""Register"")").ClickAsync(); ; + // Set data holder brand id + await page.Locator("select[name=\"DataHolderBrandId\"]").SelectOptionAsync(new[] { dhBrandId }); - // Assert - Check refresh was successful, card-footer should be showing OK etc - await page.Locator(@"h5:has-text(""Create Client Registration"") ~ div.card-footer >> text=OK").TextContentAsync(); - }); + // Assert - Check software product id + (await page.Locator("input[name=\"SoftwareProductId\"]").InputValueAsync()).Should().Be(drSoftwareProductId); + + // Act - Click Refresh button + await page.Locator(@"h5:has-text(""Create Client Registration"") ~ div.card-body >> input:has-text(""Register"")").ClickAsync(); ; + + // Assert - Check refresh was successful, card-footer should be showing OK etc + var footer = page.Locator(@"h5:has-text(""Create Client Registration"") ~ div.card-footer"); + var text = await footer.InnerTextAsync(); + text.Should().StartWith("Created - Registered"); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } - [Fact] - public async Task AC05_ConsentAndAuthorisation() + // Delete the DCR via UI since just clearing the table in arrangement doesn't seem to work (web client must be caching the DCR??) + private static async Task DeleteDCR(IPage page) + { + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Dynamic Client Registration").ClickAsync(); + await page.Locator("h2 >> text=Dynamic Client Registration").TextContentAsync(); + await page.Locator("text=Delete").ClickAsync(); + await page.Locator("text=No existing registrations found.").TextContentAsync(); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + [InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC05_ConsentAndAuthorisation( + string dhBrandId = DH_BRANDID, + string drBrandId = DR_BRANDID, + string drSoftwareProductId = DR_SOFTWAREPRODUCTID, + string customerId = CUSTOMERID_BANKING, + string customerAccounts = CUSTOMERACCOUNTS_BANKING) { await Arrange(async () => { await AC02_DiscoverDataHolders(); - await AC03_GetSSA(); - await AC04_DynamicClientRegistration(); + await AC03_GetSSA("1", drBrandId, drSoftwareProductId); + await AC04_DynamicClientRegistration(dhBrandId, drBrandId, drSoftwareProductId); }); - ConsentAndAuthorisationResponse? res = null; - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC05_ConsentAndAuthorisation)}", async (page) => + try { - // Arrange - Goto home page, click menu button, check page loaded - await page.GotoAsync(WEB_URL); - await page.Locator("text=Consent and Authorisation").ClickAsync(); - await page.Locator("h2 >> text=Consent and Authorisation").TextContentAsync(); + ConsentAndAuthorisationResponse? res = null; + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC05_ConsentAndAuthorisation)} - DH_BrandId={dhBrandId}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("text=Consent and Authorisation").ClickAsync(); + await page.Locator("h2 >> text=Consent and Authorisation").TextContentAsync(); - // Act - Select Client ID, enter Sharing Duration, click Construct Authoriation URI button - await page.Locator("select[name=\"ClientId\"]").SelectOptionAsync(new[] { GetClientId() }); - await page.Locator("input[name=\"SharingDuration\"]").FillAsync(SHARING_DURATION); - await page.Locator("text=Construct Authorisation Uri").ClickAsync(); + // Arrange - Set Client ID + await page.Locator("select[name=\"ClientId\"]").SelectOptionAsync(new[] { GetClientId() }); + await page.Locator("select[name=\"ClientId\"]").ClickAsync(); // there is JS that runs on the click event, so simulate click here + await Task.Delay(2000); - // Act - Click Authorisation URI link - await page.Locator("p.results > a").ClickAsync(); + // Arrange - Set Sharing Duration + await page.Locator("input[name=\"SharingDuration\"]").FillAsync(SHARING_DURATION); + // Arrange - Click Construct Authoriation URI button + await page.Locator("text=Construct Authorisation Uri").ClickAsync(); - // Act/Assert - Perform consent and authorisation - res = await ConsentAndAuthorisation(page); - }); + // Act - Click Authorisation URI link + await page.Locator("p.results > a").ClickAsync(); + + // Act/Assert - Perform consent and authorisation + res = await ConsentAndAuthorisation(page, customerId, customerAccounts); + }); - return res ?? throw new ArgumentNullException($"Expected {nameof(ConsentAndAuthorisationResponse)}"); + return res ?? throw new ArgumentNullException($"Expected {nameof(ConsentAndAuthorisationResponse)}"); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -315,10 +448,20 @@ await Arrange(async () => response = await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_ViewIDToken)}", async (page) => + try { - await TestToken(page, "View ID Token", response?.IDToken ?? throw new ArgumentNullException()); - }); + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_ViewIDToken)}", async (page) => + { + await TestToken(page, "View ID Token", response?.IDToken ?? throw new ArgumentNullException()); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -334,10 +477,20 @@ await Arrange(async () => response = await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_ViewAccessToken)}", async (page) => + try { - await TestToken(page, "View Access Token", response?.AccessToken ?? throw new ArgumentNullException()); - }); + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_ViewAccessToken)}", async (page) => + { + await TestToken(page, "View Access Token", response?.AccessToken ?? throw new ArgumentNullException()); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -353,10 +506,20 @@ await Arrange(async () => response = await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_ViewRefreshToken)}", async (page) => + try { - await TestToken(page, "View Refresh Token", response?.RefreshToken ?? throw new ArgumentNullException()); - }); + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_ViewRefreshToken)}", async (page) => + { + await TestToken(page, "View Refresh Token", response?.RefreshToken ?? throw new ArgumentNullException()); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -370,20 +533,30 @@ await Arrange(async () => await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_ViewUserInfo)}", async (page) => + try { - var expected = new (string, string?)[] + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_ViewUserInfo)}", async (page) => { + var expected = new (string, string?)[] + { ("given_name", "Jane"), ("family_name", "Wilson"), ("name", "Jane Wilson"), ("aud", ASSERT_JSON2_ANYVALUE), ("iss", ASSERT_JSON2_ANYVALUE), ("sub", ASSERT_JSON2_ANYVALUE), - }; + }; - await TestInfo(page, "UserInfo", "User Info", "200", expected); - }); + await TestInfo(page, "UserInfo", "User Info", "200", expected); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -399,18 +572,28 @@ await Arrange(async () => response = await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Introspect)}", async (page) => + try { - var expected = new (string, string?)[] + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Introspect)}", async (page) => { + var expected = new (string, string?)[] + { ("cdr_arrangement_id", response?.CDRArrangementID ?? throw new ArgumentNullException()), ("scope", ASSERT_JSON2_ANYVALUE), ("exp", ASSERT_JSON2_ANYVALUE), ("active", "True"), - }; + }; - await TestInfo(page, "Introspect", "Introspection", "200", expected); - }); + await TestInfo(page, "Introspect", "Introspection", "200", expected); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -424,21 +607,31 @@ await Arrange(async () => await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Refresh_Access_Token)}", async (page) => + try { - var expected = new (string, string?)[] + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Refresh_Access_Token)}", async (page) => { + var expected = new (string, string?)[] + { ("id_token", ASSERT_JSON2_ANYVALUE), ("access_token", ASSERT_JSON2_ANYVALUE), ("refresh_token", ASSERT_JSON2_ANYVALUE), ("expires_in", ACCESSTOKENLIFETIMESECONDS), ("token_type", "Bearer"), - ("scope", "openid profile bank:accounts.basic:read bank:transactions:read common:customer.basic:read bank:accounts.detail:read"), + ("scope", "openid profile cdr:registration bank:accounts.basic:read bank:transactions:read common:customer.basic:read"), ("cdr_arrangement_id", ASSERT_JSON2_ANYVALUE), - }; + }; - await TestInfo(page, "Refresh Access Token", "Refresh Access Token", "200", expected); - }); + await TestInfo(page, "Refresh Access Token", "Refresh Access Token", "200", expected); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -452,13 +645,23 @@ await Arrange(async () => await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Revoke_Arrangement)}", async (page) => + try { - await TestInfo(page, "Revoke Arrangement", "Revoke Arrangement", "204"); - await ScreenshotAsync(page, "-Modal"); + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Revoke_Arrangement)}", async (page) => + { + await TestInfo(page, "Revoke Arrangement", "Revoke Arrangement", "204"); + await ScreenshotAsync(page, "-Modal"); - await page.Locator("div#modal-info >> div.modal-footer >> a >> text=Refresh Page").ClickAsync(); - }); + await page.Locator("div#modal-info >> div.modal-footer >> a >> text=Refresh Page").ClickAsync(); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -472,10 +675,20 @@ await Arrange(async () => await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Revoke_AccessToken)}", async (page) => + try { - await TestInfo(page, "Revoke Access Token", "Revoke Access Token", "200"); - }); + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Revoke_AccessToken)}", async (page) => + { + await TestInfo(page, "Revoke Access Token", "Revoke Access Token", "200"); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -489,10 +702,20 @@ await Arrange(async () => await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Revoke_RefreshToken)}", async (page) => + try { - await TestInfo(page, "Revoke Refresh Token", "Revoke Refresh Token", "200"); - }); + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Revoke_RefreshToken)}", async (page) => + { + await TestInfo(page, "Revoke Refresh Token", "Revoke Refresh Token", "200"); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] @@ -506,43 +729,124 @@ await Arrange(async () => await AC05_ConsentAndAuthorisation(); }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Delete_Local)}", async (page) => + try { - await TestInfo(page, "Delete (local)", "Delete Arrangement", "204"); - }); + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC06_Consents_Delete_Local)}", async (page) => + { + await TestInfo(page, "Delete (local)", "Delete Arrangement", "204"); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Fact] - public async Task AC07_ConsumerDataSharing() + public async Task AC07_ConsumerDataSharing_Banking() { await Arrange(async () => { }); - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC07_ConsumerDataSharing)}", async (page) => + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC07_ConsumerDataSharing_Banking)}", async (page) => { // Arrange - Goto home page, click menu button, check page loaded await page.GotoAsync(WEB_URL); - await page.Locator("a >> text=Consumer Data Sharing").ClickAsync(); - await page.Locator("h2 >> text=Data Sharing").TextContentAsync(); + await page.Locator("a >> text=Consumer Data Sharing - Banking").ClickAsync(); + await page.Locator("h2 >> text=Data Sharing - Banking").TextContentAsync(); + await Task.Delay(2000); }); } - // [Fact] - public async Task AC08_PAR() + [Fact] + public async Task AC07_ConsumerDataSharing_Banking_AccountsGet() { + string? cdrArrangementId = null; + await Arrange(async () => { await AC02_DiscoverDataHolders(); await AC03_GetSSA(); await AC04_DynamicClientRegistration(); - await AC05_ConsentAndAuthorisation(); + cdrArrangementId = (await AC05_ConsentAndAuthorisation()).CDRArrangementID; }); + try + { + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC07_ConsumerDataSharing_Banking_AccountsGet)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Consumer Data Sharing - Banking").ClickAsync(); + await page.Locator("h2 >> text=Data Sharing - Banking").TextContentAsync(); + + // Arrange - Get Swagger iframe + var iFrame = page.FrameByUrl($"{WEB_URL}/{SWAGGER_BANKING_IFRAME}") ?? throw new Exception($"IFrame not found - {SWAGGER_BANKING_IFRAME}"); + + // Arrange - Select CDR arrangemment + await iFrame.SelectOptionAsync("select", new[] { + cdrArrangementId ?? throw new NullReferenceException(nameof(cdrArrangementId)) + }); + + // Arrange - Click GET​/banking​/accountsGet Accounts + await iFrame.ClickAsync("text=GET​/banking​/accountsGet Accounts"); + + // Arrange - Click Try it out + await iFrame.ClickAsync("text=Try it out"); + + // Arrange - Set x-v + await iFrame.FillAsync("[placeholder=\"x-v\"]", "1"); + + // Act - Click Execute + await iFrame.ClickAsync("text=Execute"); + + // Assert - Status code should be 200 + var statusCode = await iFrame.Locator("div.responses-inner > div > div > table > tbody > tr > td.response-col_status").TextContentAsync(); + statusCode.Should().Be("200"); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } + } + + // [Fact] + // public async Task AC07_ConsumerDataSharing_Energy() // TODO - MJS - see AC07_ConsumerDataSharing_Banking_AccountsGet, need to test endpoint + // { + // await Arrange(async () => { }); + + // await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC07_ConsumerDataSharing_Energy)}", async (page) => + // { + // // Arrange - Goto home page, click menu button, check page loaded + // await page.GotoAsync(WEB_URL); + // await page.Locator("a >> text=Consumer Data Sharing - Energy").ClickAsync(); + // await page.Locator("h2 >> text=Data Sharing - Energy").TextContentAsync(); + // await Task.Delay(2000); + // }); + // } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + [InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC08_PAR( + string dhBrandId = DH_BRANDID, + string drBrandId = DR_BRANDID, + string drSoftwareProductId = DR_SOFTWAREPRODUCTID, + string customerId = CUSTOMERID_BANKING, + string customerAccounts = CUSTOMERACCOUNTS_BANKING) + { static string GetCDRArrangementId() { - using var mdrConnection = new SqliteConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); + using var mdrConnection = new SqlConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); mdrConnection.Open(); - using var selectCommand = new SqliteCommand($"select cdrarrangementid from cdrarrangement", mdrConnection); + using var selectCommand = new SqlCommand($"select cdrarrangementid from cdrarrangement", mdrConnection); string? cdrArrangementId = Convert.ToString(selectCommand.ExecuteScalar()); if (String.IsNullOrEmpty(cdrArrangementId)) @@ -551,27 +855,49 @@ static string GetCDRArrangementId() return cdrArrangementId; } - await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC08_PAR)}", async (page) => + await Arrange(async () => { - // Arrange - Goto home page, click menu button, check page loaded - await page.GotoAsync(WEB_URL); - await page.Locator("a >> text=PAR").ClickAsync(); - await page.Locator("h2 >> text=Pushed Authorisation Request (PAR)").TextContentAsync(); - - // Arrange - Select Client ID, CdrArrangementId, enter Sharing Duration, click Initate PAR button - await page.Locator("select[name=\"ClientId\"]").SelectOptionAsync(new[] { GetClientId() }); - await page.Locator("select[name=\"CdrArrangementId\"]").SelectOptionAsync(new[] { GetCDRArrangementId() }); - await page.Locator("input[name=\"SharingDuration\"]").FillAsync(SHARING_DURATION); - - // Act - Click Initiate PAR button - await page.Locator("div.form >> text=Initiate PAR").ClickAsync(); - - // Act - Click request uri - await page.Locator("p.results > a").ClickAsync(); - - // Act/Assert - Perform consent and authorisation - await ConsentAndAuthorisation(page); + await AC02_DiscoverDataHolders(); + await AC03_GetSSA("1", drBrandId, drSoftwareProductId); + await AC04_DynamicClientRegistration(dhBrandId, drBrandId, drSoftwareProductId); + await AC05_ConsentAndAuthorisation(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts); }); + + try + { + await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC08_PAR)} - DH_BrandId={dhBrandId}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=PAR").ClickAsync(); + await page.Locator("h2 >> text=Pushed Authorisation Request (PAR)").TextContentAsync(); + + // Arrange - Set Client ID + await page.Locator("select[name=\"ClientId\"]").SelectOptionAsync(new[] { GetClientId() }); + await page.Locator("select[name=\"ClientId\"]").ClickAsync(); // there is JS that runs on the click event, so simulate click here + await Task.Delay(2000); + // Arrange - Set CdrArrangementId + await page.Locator("select[name=\"CdrArrangementId\"]").SelectOptionAsync(new[] { GetCDRArrangementId() }); + // Arrange - Set Sharing Duration + await page.Locator("input[name=\"SharingDuration\"]").FillAsync(SHARING_DURATION); + + // Act - Click Initiate PAR button + await page.Locator("div.form >> text=Initiate PAR").ClickAsync(); + + // Act - Click request uri + await page.Locator("p.results > a").ClickAsync(); + + // Act/Assert - Perform consent and authorisation + await ConsentAndAuthorisation(page, customerId, customerAccounts); + }); + } + finally + { + await CleanupAsync(async (page) => + { + await DeleteDCR(page); + }); + } } [Theory] @@ -596,7 +922,8 @@ await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC09_IDTokenHelper)}" // Assert - Check results await TestResults(page, "nbf", "1635114387"); await TestResults(page, "exp", "1635114687"); - await TestResults(page, "iss", "https://localhost:8001"); + // await TestResults(page, "iss", $"https://{BaseTest.HOSTNAME_DATAHOLDER}:8001"); + await TestResults(page, "iss", $"https://localhost:8001"); // token is const, it was created on localhost, we are just checking the decryption of token works and not where it was issued await TestResults(page, "aud", "ffd1f415-a576-4e3e-9eab-1f732bbf55c6"); await TestResults(page, "nonce", "38ff9cc4-57c4-404a-98ec-5e519336d419"); await TestResults(page, "iat", "1635114387"); @@ -644,7 +971,7 @@ await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC10_PrivateKeyJWTGen await TestResults(page, "iat"); // just check claim exists await TestResults(page, "exp"); // just check claim exists await TestResults(page, "iss", "c6327f87-687a-4369-99a4-eaacd3bb8210"); - await TestResults(page, "aud", "https://localhost:7001/idp/connect/token"); + await TestResults(page, "aud", $"https://{BaseTest.HOSTNAME_REGISTER}:7001/idp/connect/token"); }); } @@ -672,4 +999,6 @@ await TestAsync($"{nameof(US23863_MDR_E2ETests)} - {nameof(AC12_About)}", async }); } } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/US23863_MDR_E2ETests_v2.cs b/Source/CDR.DataRecipient.E2ETests/US23863_MDR_E2ETests_v2.cs new file mode 100644 index 0000000..a566e7e --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/US23863_MDR_E2ETests_v2.cs @@ -0,0 +1,1054 @@ +using FluentAssertions; +using Microsoft.Data.SqlClient; +using Microsoft.Playwright; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; + +#nullable enable + +namespace CDR.DataRecipient.E2ETests +{ + public class US23863_MDR_E2ETests_v2 : BaseTest_v2, IClassFixture + { + private const string SWAGGER_BANKING_IFRAME = "cds-banking/index.html"; + private const string SWAGGER_ENERGY_IFRAME = "cds-energy/index.html"; + private const string SWAGGER_COMMON_IFRAME = "cds-common/index.html"; + + private const string SHARING_DURATION = "100000"; + + // Pre-generated ID Token used in IDTokenhelper test + const string IDTOKEN = @"eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJraWQiOiJlMmM2ZWFmZjdmYWQwODFjNzhiMjJkNjNiYmI1N" + + "jdlODYwNzBlNTFlYjE0NzZhYmNhNmEyMzNiY2U4Y2ExNGJhIn0.fp9-2--a7mM70FsVL1c5MacViVkPcI-CZCGXyjV4F1T-RZuUsMaw9sCkjNrnE3" + + "LR9nnBOYploFXljRo6_ZkH5PJHtSfnoF8GRnJJHJ74dvJC3MqRsvGUl8uS5P2sEW2TexXQlhdKwFA3REM1khpVNAA1FZyFK3iv7IucipnL0UcO1H-" + + "23iBb7puOdEm6_3Sndu2ycACt5in-gO2UIWHFeaUDwLdr7iCBH4fzn5jupSJdyZ-9iU2ahOhf6iJFAwYM4R7CEPRTr8h8JqXBW3cqOcAktK0jScmv" + + "U3k2zOqtiwTxZ3yTwNEinSSvDxyxofKmiXsQDkgOzbJt6YPAq2c9gw.o-hgXFF8FzFUd1gY.NX-J0RWfE53KksdvhNK9pcXjXvLicaFO3N1N-ivAV" + + "G3HL_7k7f4L2d7B3Elh4UXiiV84xuS2wBltNT2XcOAEMZuJd6-e1Octuhzzc9o8pFQEtP-72vzpo6K6wbdSgFwqPNQ4xGJTArS2BCG1v_rfiUNqM7" + + "Y-igdsGImk3DoCBtsq-PWaWZgwj0d4ci5De4EkMpb3UZrk9UlZGGpgOH0rqGEPQEhO41M-7XeBw-cVqyGwaS6c3iwSUZHHCLgluZ-AfJ3ebfq9ya3" + + "u02de95C1YMhN04BA9Oj_tkTUA4XvyfXnxd_cXtjPUUjAo2Tvmc1YxU-tfNgwLgW3s2jFdkeJnHj7vwXzAbiAthIleD9D2LrYUN_vNWI0Lc570R1g" + + "GVXVFl_IfUMhZBSRYTl4z15NGdTwTopusNDVnOKQrKu5FsRWa0g1h80Fnmiw4sNRByFzxY_qziz67aUbJK1qz57FdBhHy85GkdK90Zd7kTuITYkPc" + + "c7_Srtu6ZHMWNRbUxvEHF_YHnTVWiH3DCiGYwrPCYEcXLutoY2A0nJGBAPsgCYnZ8_FvsQCsUno-PJyyWhjZ98mXcmtNIBOw5qArH7E520p586FtO" + + "JjS0zbRL7UjNxK2IcSB01-9WkWVxTxYrQnD8fzobnNPCf6esGGyPjU-PD-bstCQ1PUhA5OSg7MmBiTyRZYfvj59_rkhqdLovYCqyZLu9NbySLoFiq" + + "hnCXmmCROv6U_-KDW0-y30Uf9s_ke00l5kBSs9F4h8shDF5rXySL8HeAwNt_0JY4Q1pg6zu2PISuXVmcnizCZoCFaDTQ1ReQKHBfsDss7g680F6OY" + + "_UFxzYwxowIctfZzKQtT0q0J2xghgjPP-U47ng8VTQX2b_8TmMMWXiEvumxEb9gHp_i6246uHOeuiBu2LVGniAJkbTB2DHgICXgRYSd_pQTi7GBsu" + + "m4ZzQeVIVC7UKxc1OOHkLLypzPRK2bwOIg0SMZjnugCLbmQUyJxyB7ht5iA2psX-EavKeR-KjTqOWFSr5byOIbMUSLY44K0Al503u7NTvH5JVUH4y" + + "y6zI8sgiaQTcfAXo1YKhmHqJPf4VbQZRMTs3_2tdu5rNl-BSytbLnKrmFvL85RoKAq6wqE3Clk4BLJQ0CNoBvm-nObhzhQ_mhbXyRXn7A1vKEkf_p" + + "KHv3-dKBlX4-jdyFJAwd_HPqb6gtBFsKROlpQwlCxGbEV5GF2iN0az03r6RPveqxvkP4RpgfG8VaXvKyW9xi4lENVelt_Ep11BXHsrJGKupIaIdW" + + "IhUZu90VJYIezKKztLycPlxs7oOkEDTIfVrO1HeuEOHk1CCgxBiWtqZiKO2ELtE5mj2fee35fWFQ31muNiXBVD2DgHabnb_S0ZXHzY6MR368Rj0h" + + "xqxiDVc6ppQcVt02XYL4HLz4mBExyvy0F13OfuEkP5tWlaHkK8k90eISkn7aKcoMVV5JSFjqPasA_dY91Gbpq0itHDtaEIzgcOYWP-u8LUGJGLF4N" + + "qWkBfZUEGxgPIQ1ynRGwwUwnrh8xQSuvG_Phid0DGHm0Kxz_j0Vyvr60TpFoYNwGPH6vQ3bsiSs2JlxLuOdC-Kw6YVahxsGkE6b9ZKn9HiW6tmxj-" + + "CCf1u4tYiYxW48ceOcivydgT-mIKAdQeClTIbAJdJq4wY_936f5GWIJxM-wJ78qwFTN4R7zG4vINi2gd5000h4JjCaYTyX9v989Fzuq5SIkNHRb8E" + + "hSLcMA_3De7epFZCnImEhkKUQPHxwaW9kDBExy-sVJ2ku9EN6k4AZAM60lCMAdOGWwvOFN-pW9k9DBDmZTfg1kjfnbn4guIfw7lJKp2iy-0TGVhDD" + + "3MN3BTrucmURy6_kpXWRLGuLd3fEj-bQAwD4sMgLVe_GWh6f1TFo7hUfrNmwuXLjqtFMjMgWXbo8zM4VJDL6fCO_U0HZzXx3CGzxuSETWQxF9EeDG" + + "kSpwIdweEmFl1finL1g.gTClNE4BztTzJIpe8BcNRw"; + + static string GetClientId() + { + using var mdrConnection = new SqlConnection(BaseTest_v2.DATARECIPIENT_CONNECTIONSTRING); + mdrConnection.Open(); + + using var selectCommand = new SqlCommand($"select clientid from registration", mdrConnection); + string? clientId = Convert.ToString(selectCommand.ExecuteScalar()); + + if (String.IsNullOrEmpty(clientId)) + throw new Exception("No registrations found"); + + return clientId; + } + + public class ConsentAndAuthorisationResponse + { + public string? IDToken { get; init; } + public string? AccessToken { get; init; } + public string? RefreshToken { get; init; } + public string? ExpiresIn { get; init; } + public string? Scope { get; init; } + public string? TokenType { get; init; } + public string? CDRArrangementID { get; init; } + } + + static async Task ConsentAndAuthorisation2(IPage page, string customerId = CUSTOMERID_BANKING, string customerAccounts = CUSTOMERACCOUNTS_BANKING) + { + // Act - Enter Customer ID + await page.Locator("[placeholder=\"Your Customer ID\"]").FillAsync(customerId); + await page.Locator("text=Continue").ClickAsync(); + + // Act - Wait for OTP, then enter it, and click Continue + await Task.Delay(5000); + await page.Locator("[placeholder=\"Enter 6 digit One Time Password\"]").FillAsync("000789"); + await page.Locator("text=Continue").ClickAsync(); + + // Act - Select accounts + foreach (var customerAccount in customerAccounts.Split(',')) + { + await page.Locator($"text={customerAccount}").ClickAsync(); + } + + // Act - Click Continue and I confirm + await page.Locator("text=Continue").ClickAsync(); + await page.Locator("text=I Confirm").ClickAsync(); + + // Assert - Check callback is shown and get arrangement ID + await page.Locator("text=Consent and Authorisation - Callback").TextContentAsync(); + + return new ConsentAndAuthorisationResponse + { + IDToken = await page.Locator(@"dt:has-text(""Id Token"") + dd ").TextContentAsync(), + AccessToken = await page.Locator(@"dt:has-text(""Access Token"") + dd ").TextContentAsync(), + RefreshToken = await page.Locator(@"dt:has-text(""Refresh Token"") + dd ").TextContentAsync(), + ExpiresIn = await page.Locator(@"dt:has-text(""Expires In"") + dd ").TextContentAsync(), + Scope = await page.Locator(@"dt:has-text(""Scope"") + dd ").TextContentAsync(), + TokenType = await page.Locator(@"dt:has-text("" Token Type"") + dd ").TextContentAsync(), + CDRArrangementID = await page.Locator(@"dt:has-text(""CDR Arrangement Id"") + dd ").TextContentAsync() + }; + } + + static async Task NewConsentAndAuthorisationWithPAR(IPage page, string dhClientId, string customerId = CUSTOMERID_BANKING, string customerAccounts = CUSTOMERACCOUNTS_BANKING) + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=PAR").ClickAsync(); + await page.Locator("h2 >> text=Pushed Authorisation Request (PAR)").TextContentAsync(); + + // Arrange - Set Client ID + await page.Locator("select[name=\"ClientId\"]").SelectOptionAsync(new[] { dhClientId! }); + await page.Locator("select[name=\"ClientId\"]").ClickAsync(); // there is JS that runs on the click event, so simulate click here + await Task.Delay(2000); + // Arrange - Set CdrArrangementId + //await page.Locator("select[name=\"CdrArrangementId\"]").SelectOptionAsync(new[] { cdrArrangement!.CDRArrangementID ?? throw new NullReferenceException(nameof(cdrArrangement.CDRArrangementID)) }); + // Arrange - Set Sharing Duration + await page.Locator("input[name=\"SharingDuration\"]").FillAsync(SHARING_DURATION); + + // Act - Click Initiate PAR button + await page.Locator("div.form >> text=Initiate PAR").ClickAsync(); + + // Act - Click request uri + await page.Locator("p.results > a").ClickAsync(); + + return await ConsentAndAuthorisation2(page, customerId, customerAccounts); + } + + public static async Task TestToken(IPage page, string menuText, string? expectedToken) + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Consents").ClickAsync(); + await page.Locator("h2 >> text=Consents").TextContentAsync(); + + // Act - Click actions button and submenu item + await page.Locator("button:has-text(\"Actions\")").ClickAsync(); + await page.Locator($"a >> text={menuText}").ClickAsync(); + + // Act - Check modal opens + await page.Locator("div#modal-token >> h5.modal-title >> text=Token Contents").TextContentAsync(); + + // Assert - Check actual token matches expected token + var token = await page.Locator(@"div#modal-token >> div.modal-body").TextContentAsync(); + token.Should().NotBeNullOrEmpty(); + token.Should().Be(expectedToken); + } + + public static async Task TestInfo(IPage page, string menuText, string modalTitle, string expectedStatusCode, (string name, string? value)[]? expectedPayload = null) + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Consents").ClickAsync(); + await page.Locator("h2 >> text=Consents").TextContentAsync(); + + // Act - Click actions button and submenu item + await page.Locator("button:has-text(\"Actions\")").ClickAsync(); + await page.Locator($"a >> text={menuText}").ClickAsync(); + + // Act - Check modal opens + await page.Locator($"div#modal-info >> h5.modal-title >> text={modalTitle}").TextContentAsync(); + + // Assert - Check statuscode + var statusCode = await page.Locator(@$"div#modal-info >> div.modal-statusCode >> text={expectedStatusCode}").TextContentAsync(); + statusCode.Should().Be(expectedStatusCode); + + // Assert - Check payload is what's expected + if (expectedPayload != null) + { + var payload = await page.Locator(@"div#modal-info >> pre.modal-payload").TextContentAsync(); + Assert_Json2(payload, expectedPayload); + } + } + + static async Task TestResults(IPage page, string label, string? value = null) + { + // Check for label and value + if (value != null) + await page.Locator($"div.results >> dl >> dt:has-text(\"{label}\") + dd:has-text(\"{value}\")").TextContentAsync(); + // Just check for label + else + await page.Locator($"div.results >> dl >> dt:has-text(\"{label}\")").TextContentAsync(); + } + + [Fact] + public async Task AC01_HomePage() + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC01_HomePage)}", async (page) => + { + // Act - Goto home page + await page.GotoAsync(WEB_URL); + + // Assert - Check banner + await page.Locator("h1 >> text=Mock Data Recipient").TextContentAsync(); + await page.Locator("text=Welcome to the Mock Data Recipient").TextContentAsync(); + await page.Locator("a >> text=Settings").TextContentAsync(); + await page.Locator("a >> text=About").TextContentAsync(); + + // Assert - Check menu items exists + await page.Locator("a >> text=Home").TextContentAsync(); + await page.Locator("a >> text=Discover Data Holders").TextContentAsync(); + await page.Locator("a >> text=Get SSA").TextContentAsync(); + await page.Locator("a >> text=Dynamic Client Registration").TextContentAsync(); + await page.Locator("a >> text=Consent and Authorisation").TextContentAsync(); + await page.Locator("a >> text=Consents").TextContentAsync(); + await page.Locator("a >> text=Consumer Data Sharing - Common").TextContentAsync(); + await page.Locator("a >> text=Consumer Data Sharing - Banking").TextContentAsync(); + await page.Locator("a >> text=Consumer Data Sharing - Energy").TextContentAsync(); + await page.Locator("a >> text=PAR").TextContentAsync(); + await page.Locator("span >> text=Utilities").TextContentAsync(); + await page.Locator("a >> text=ID Token Helper").TextContentAsync(); + await page.Locator("a >> text=Private Key JWT Generator").TextContentAsync(); + }); + } + + static private async Task DataHolders_Discover(IPage page, string industry = "ALL", string version = "2", int? expectedRecords = 32, string? expectedError = null) + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Discover Data Holders").ClickAsync(); + await page.Locator("h2 >> text=Discover Data Holders").TextContentAsync(); + + // Arrange - Set industry + if (String.IsNullOrEmpty(industry)) // Clear industry + { + await page.Locator("select[name=\"Industry\"]").SelectOptionAsync(new SelectOptionValue[] { }); + } + else + { + await page.Locator("select[name=\"Industry\"]").SelectOptionAsync(new[] { industry switch + { + // "" => "", // Doesn't work for clearing, use SelectOptionAsync(new SelectOptionValue[] { }) instead (see above) + "ALL" => "0", + "BANKING" => "1", + "ENERGY" => "2", + "TELCO" => "3", + _ => throw new ArgumentOutOfRangeException($"{nameof(industry)}") + }}); + } + + // Arrange - Set version + await page.Locator("input[name=\"Version\"]").FillAsync(version); + + // Act - Click Refresh button + await page.Locator(@"h5:has-text(""Refresh Data Holders"") ~ div.card-body >> input:has-text(""Refresh"")").ClickAsync(); + + // Assert - Check refresh was successful + var footer = page.Locator(@"h5:has-text(""Refresh Data Holders"") ~ div.card-footer"); + var text = await footer.InnerTextAsync(); + if (expectedError != null) + { + text.Should().Be(expectedError); + } + else + { + if (expectedRecords != -1) // -1 = don't bother checking + { + text.Should().Be($"OK: {expectedRecords} data holder brands added. 0 data holder brands updated."); + } + } + } + + [Fact] + public async Task AC02_01_DiscoverDataHolders_Banking() + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC02_01_DiscoverDataHolders_Banking)}", async (page) => + { + await DataHolders_Discover(page, "BANKING", "1", 30); + }); + } + + [Fact] + public async Task AC02_02_DiscoverDataHolders_Energy() + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC02_02_DiscoverDataHolders_Energy)}", async (page) => + { + await DataHolders_Discover(page, "ENERGY", "2", 2); + }); + } + + [Fact] + public async Task AC02_03_DiscoverDataHolders_Telco() + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC02_03_DiscoverDataHolders_Telco)}", async (page) => + { + await DataHolders_Discover(page, "TELCO", "2", 0); // Currently no Telco dataholders, so 0 = no additional dataholders loaded + }); + } + + [Fact] + public async Task AC02_04_DiscoverDataHolders_AnyIndustry() + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC02_04_DiscoverDataHolders_AnyIndustry)}", async (page) => + { + await DataHolders_Discover(page, "ALL", "2", 0); // Should have loaded all dataholders by now, so 0 = no additional dataholders loaded + }); + } + + [Theory] + //[InlineData("ALL", "", null, "BadRequest - Bad Request")] // DF: won't fail anymore + [InlineData("ALL", "3", null, "NotAcceptable - Not Acceptable")] + [InlineData("ALL", "foo", null, "BadRequest - Bad Request")] + //[InlineData("BANKING", "", null, "BadRequest - Bad Request")] // DF: won't fail anymore + [InlineData("BANKING", "3", null, "NotAcceptable - Not Acceptable")] + [InlineData("BANKING", "foo", null, "BadRequest - Bad Request")] + //[InlineData("ENERGY", "", null, "BadRequest - Bad Request")] // DF: won't fail anymore + [InlineData("ENERGY", "3", null, "NotAcceptable - Not Acceptable")] + [InlineData("ENERGY", "foo", null, "BadRequest - Bad Request")] + //[InlineData("TELCO", "", null, "BadRequest - Bad Request")] // DF: won't fail anymore + [InlineData("TELCO", "3", null, "NotAcceptable - Not Acceptable")] + [InlineData("TELCO", "foo", null, "BadRequest - Bad Request")] + public async Task AC02_99_DiscoverDataHolders(string industry = "ALL", string version = "2", int? expectedRecords = 32, string? expectedError = null) + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC02_99_DiscoverDataHolders)} - Industry={industry} - Version={version}", async (page) => + { + await DataHolders_Discover(page, industry, version, expectedRecords, expectedError); + }); + } + + static private async Task SSA_Get(IPage page, string industry, string version, string drBrandId, string drSoftwareProductId, string expectedMessage) + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Get SSA").ClickAsync(); + await page.Locator("h2 >> text=Get Software Statement Assertion").TextContentAsync(); + + // Set version + await page.Locator("input[name=\"Version\"]").FillAsync(version); + // Set brandId + await page.Locator("input[name=\"BrandId\"]").FillAsync(drBrandId); + // Set softwareProductId + await page.Locator("input[name=\"SoftwareProductId\"]").FillAsync(drSoftwareProductId); + // Set industry + await page.Locator("select[name=\"Industry\"]").SelectOptionAsync(new[] { industry switch + { + // "" => "", // Doesn't work for clearing, use SelectOptionAsync(new SelectOptionValue[] { }) instead (see above) + "ALL" => "0", + "BANKING" => "1", + "ENERGY" => "2", + "TELCO" => "3", + _ => throw new ArgumentOutOfRangeException($"{nameof(industry)}") + }}); + + // Act - Click Refresh button + await page.Locator(@"h5:has-text(""Get SSA"") ~ div.card-body >> input:has-text(""Get SSA"")").ClickAsync(); + + // Assert - Check refresh was successful, card-footer should be showing OK - SSA Generated + var footer = page.Locator(@"h5:has-text(""Get SSA"") ~ div.card-footer"); + var text = await footer.InnerTextAsync(); + text.Should().StartWith(expectedMessage); + } + + [Theory] + //[InlineData("", DR_BRANDID, DR_SOFTWAREPRODUCTID, "BadRequest")] // DF: no longer an error + [InlineData("BANKING", "1", DR_BRANDID, DR_SOFTWAREPRODUCTID, "OK - SSA Generated")] + [InlineData("BANKING", "2", DR_BRANDID, DR_SOFTWAREPRODUCTID, "OK - SSA Generated")] + [InlineData("BANKING", "3", DR_BRANDID, DR_SOFTWAREPRODUCTID, "OK - SSA Generated")] + [InlineData("BANKING", "4", DR_BRANDID, DR_SOFTWAREPRODUCTID, "NotAcceptable")] + public async Task AC03_GetSSA(string industry, string version, string drBrandId, string drSoftwareProductId, string expectedMessage) + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC03_GetSSA)} - Version={version} - DR_BrandId={drBrandId} - DR_SoftwareProductId={drSoftwareProductId}", async (page) => + { + await SSA_Get(page, industry, version, drBrandId, drSoftwareProductId, expectedMessage); + }); + } + + private class DCRResponse + { + [JsonProperty("client_id")] + public string? ClientId { get; set; } + } + + // Create Client Registration returning DH client ID of client that was registered + static private async Task ClientRegistration_Create(IPage page, string dhBrandId, string drBrandId, string drSoftwareProductId) + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Dynamic Client Registration").ClickAsync(); + await page.Locator("h2 >> text=Dynamic Client Registration").TextContentAsync(); + + // Set data holder brand id + await page.Locator("select[name=\"DataHolderBrandId\"]").SelectOptionAsync(new[] { dhBrandId }); + + // Assert - Check software product id + (await page.Locator("input[name=\"SoftwareProductId\"]").InputValueAsync()).Should().Be(drSoftwareProductId); + + // Act - Click create button + await page.Locator(@"h5:has-text(""Create Client Registration"") ~ div.card-body >> input:has-text(""Register"")").ClickAsync(); + + // Assert - Check client was registered + await page.Locator(@"h5:has-text(""Create Client Registration"") ~ div.card-footer:has-text(""Created - Registered"")").TextContentAsync(); + + // Assert - Get json result + var json = await page.Locator(@"h5:has-text(""Create Client Registration"") ~ div.card-footer >> pre").InnerTextAsync(); + + // Deserialise response and return DH client id + DCRResponse dcrResponse = JsonConvert.DeserializeObject(json) ?? throw new NullReferenceException(nameof(json)); + return dcrResponse.ClientId ?? throw new NullReferenceException(nameof(dcrResponse.ClientId)); + } + + // Delete Client Registration + static private async Task ClientRegistration_Delete(IPage page) + { + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Dynamic Client Registration").ClickAsync(); + await page.Locator("h2 >> text=Dynamic Client Registration").TextContentAsync(); + await page.Locator("text=Delete").ClickAsync(); + await page.Locator("text=No existing registrations found.").TextContentAsync(); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID)] + [InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID)] // Also test for Energy DH + public async Task AC04_DynamicClientRegistration(string dhBrandId = DH_BRANDID, string drBrandId = DR_BRANDID, string drSoftwareProductId = DR_SOFTWAREPRODUCTID) + { + try + { + await ArrangeAsync(async (page) => + { + await DataHolders_Discover(page, "ALL", "2", -1); // get all dh brands + await SSA_Get(page, "ALL", "3", drBrandId, drSoftwareProductId, "OK - SSA Generated"); + }); + + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC04_DynamicClientRegistration)} - DH_BrandId={dhBrandId} - DR_BrandId={drBrandId} - DR_SoftwareProductId={drSoftwareProductId}", async (page) => + { + await ClientRegistration_Create(page, dhBrandId, drBrandId, drSoftwareProductId); + }); + } + finally + { + await CleanupAsync(async (page) => + { + try { await ClientRegistration_Delete(page); } catch { }; + }); + } + } + + static private async Task ConsentAndAuthorisation( + IPage page, + string dhClientId, + string dhBrandId, + string drBrandId, + string drSoftwareProductId, + string customerId, + string customerAccounts) + { + ConsentAndAuthorisationResponse? res = null; + + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("text=Consent and Authorisation").ClickAsync(); + await page.Locator("h2 >> text=Consent and Authorisation").TextContentAsync(); + + // Arrange - Set Client ID + await page.Locator("select[name=\"ClientId\"]").SelectOptionAsync(dhClientId); + await page.Locator("select[name=\"ClientId\"]").ClickAsync(); // there is JS that runs on the click event, so simulate click here + await Task.Delay(2000); + + // Arrange - Set Sharing Duration + await page.Locator("input[name=\"SharingDuration\"]").FillAsync(SHARING_DURATION); + // Arrange - Click Construct Authoriation URI button + await page.Locator("text=Construct Authorisation Uri").ClickAsync(); + + // Act - Click Authorisation URI link + await page.Locator("p.results > a").ClickAsync(); + + // Act/Assert - Perform consent and authorisation + res = await ConsentAndAuthorisation2(page, customerId, customerAccounts); + + return res ?? throw new ArgumentNullException($"Expected {nameof(ConsentAndAuthorisationResponse)}"); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Don't test for Energy as error will be raised due to FAPI 1.0 conformance + public async Task AC05_ConsentAndAuthorisation( + string dhBrandId = DH_BRANDID, + string drBrandId = DR_BRANDID, + string drSoftwareProductId = DR_SOFTWAREPRODUCTID, + string customerId = CUSTOMERID_BANKING, + string customerAccounts = CUSTOMERACCOUNTS_BANKING) + { + try + { + string? dhClientId = null; + await ArrangeAsync(async (page) => + { + await DataHolders_Discover(page, "ALL", "2", -1); // get all dh brands + await SSA_Get(page, "ALL", "3", drBrandId, drSoftwareProductId, "OK - SSA Generated"); + dhClientId = await ClientRegistration_Create(page, dhBrandId, drBrandId, drSoftwareProductId) ?? throw new NullReferenceException(nameof(dhClientId)); + }); + + ConsentAndAuthorisationResponse? res = null; + + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC05_ConsentAndAuthorisation)} - DH_BrandId={dhBrandId}", async (page) => + { + res = await ConsentAndAuthorisation(page, dhClientId!, dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts); + }); + } + finally + { + await CleanupAsync(async (page) => + { + try { await ClientRegistration_Delete(page); } catch { }; + try { await Consents_DeleteLocal(page); } catch { }; + }); + } + } + + public delegate Task ConsentsDelegate(IPage page, ConsentAndAuthorisationResponse response); + public async Task Test_Consents(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts, string testName, ConsentsDelegate test) + { + try + { + string? dhClientId = null; + ConsentAndAuthorisationResponse? cdrArrangement = null; + await ArrangeAsync(async (page) => + { + await DataHolders_Discover(page, "ALL", "2", -1); // get all dh brands + await SSA_Get(page, "ALL", "3", drBrandId, drSoftwareProductId, "OK - SSA Generated"); + dhClientId = await ClientRegistration_Create(page, dhBrandId, drBrandId, drSoftwareProductId) + ?? throw new NullReferenceException(nameof(dhClientId)); + cdrArrangement = await ConsentAndAuthorisation(page, dhClientId, dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts); + }); + + await TestAsync($"{testName} - DH_BrandId={dhBrandId}", async (page) => + { + await test(page, cdrArrangement ?? throw new NullReferenceException(nameof(cdrArrangement))); + }); + } + finally + { + await CleanupAsync(async (page) => + { + try { await ClientRegistration_Delete(page); } catch { }; + try { await Consents_DeleteLocal(page); } catch { }; + }); + } + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_ViewIDToken(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_ViewIDToken)}", async (page, response) => + { + await TestToken(page, "View ID Token", response?.IDToken ?? throw new ArgumentNullException(nameof(response.IDToken))); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_ViewAccessToken(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_ViewAccessToken)}", async (page, response) => + { + await TestToken(page, "View Access Token", response?.AccessToken ?? throw new ArgumentNullException(nameof(response.AccessToken))); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_ViewRefreshToken(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_ViewRefreshToken)}", async (page, response) => + { + await TestToken(page, "View Refresh Token", response?.RefreshToken ?? throw new ArgumentNullException(nameof(response.RefreshToken))); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + // [InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_ViewUserInfo(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_ViewUserInfo)}", async (page, response) => + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_ViewUserInfo)}", async (page) => + { + var expected = new (string, string?)[] + { + ("given_name", "Jane"), + ("family_name", "Wilson"), + ("name", "Jane Wilson"), + ("aud", ASSERT_JSON2_ANYVALUE), + ("iss", ASSERT_JSON2_ANYVALUE), + ("sub", ASSERT_JSON2_ANYVALUE), + }; + + await TestInfo(page, "UserInfo", "User Info", "200", expected); + }); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_Introspect(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_Introspect)}", async (page, response) => + { + var expected = new (string, string?)[] + { + ("cdr_arrangement_id", response?.CDRArrangementID ?? throw new ArgumentNullException(nameof(response.CDRArrangementID))), + ("scope", ASSERT_JSON2_ANYVALUE), + ("exp", ASSERT_JSON2_ANYVALUE), + ("active", "True"), + }; + + await TestInfo(page, "Introspect", "Introspection", "200", expected); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING, + "openid profile cdr:registration bank:accounts.basic:read bank:transactions:read common:customer.basic:read")] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY, + // "openid profile cdr:registration energy:accounts.basic:read energy:accounts.concessions:read common:customer.basic:read")] // Also test for Energy DH + public async Task AC06_Consents_Refresh_Access_Token(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts, string expectedScope) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_Refresh_Access_Token)}", async (page, response) => + { + var expected = new (string, string?)[] + { + ("id_token", ASSERT_JSON2_ANYVALUE), + ("access_token", ASSERT_JSON2_ANYVALUE), + ("refresh_token", ASSERT_JSON2_ANYVALUE), + ("expires_in", ACCESSTOKENLIFETIMESECONDS), + ("token_type", "Bearer"), + ("scope", expectedScope), + ("cdr_arrangement_id", ASSERT_JSON2_ANYVALUE), + }; + + await TestInfo(page, "Refresh Access Token", "Refresh Access Token", "200", expected); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_Revoke_Arrangement(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_Revoke_Arrangement)}", async (page, response) => + { + await TestInfo(page, "Revoke Arrangement", "Revoke Arrangement", "204"); + await ScreenshotAsync(page, "-Modal"); + + await page.Locator("div#modal-info >> div.modal-footer >> a >> text=Refresh Page").ClickAsync(); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_Revoke_AccessToken(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_Revoke_AccessToken)}", async (page, response) => + { + await TestInfo(page, "Revoke Access Token", "Revoke Access Token", "200"); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_Revoke_RefreshToken(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_Revoke_RefreshToken)}", async (page, response) => + { + await TestInfo(page, "Revoke Refresh Token", "Revoke Refresh Token", "200"); + }); + } + + private static async Task Consents_DeleteLocal(IPage page) + { + await TestInfo(page, "Delete (local)", "Delete Arrangement", "204"); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC06_Consents_Delete_Local(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + await Test_Consents(dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts, $"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC06_Consents_Delete_Local)}", async (page, response) => + { + await Consents_DeleteLocal(page); + }); + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + //[InlineData(DH_BRANDID_ENERGY, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_ENERGY, CUSTOMERACCOUNTS_ENERGY)] // Also test for Energy DH + public async Task AC07_PAR(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + try + { + string? dhClientId = null; + ConsentAndAuthorisationResponse? cdrArrangement = null; + await ArrangeAsync(async (page) => + { + await DataHolders_Discover(page, "ALL", "2", -1); // get all dh brands + await SSA_Get(page, "ALL", "3", drBrandId, drSoftwareProductId, "OK - SSA Generated"); + dhClientId = await ClientRegistration_Create(page, dhBrandId, drBrandId, drSoftwareProductId) + ?? throw new NullReferenceException(nameof(dhClientId)); + cdrArrangement = await ConsentAndAuthorisation(page, dhClientId, dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts) + ?? throw new NullReferenceException(nameof(cdrArrangement)); + }); + + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC07_PAR)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=PAR").ClickAsync(); + await page.Locator("h2 >> text=Pushed Authorisation Request (PAR)").TextContentAsync(); + + // Arrange - Set Client ID + await page.Locator("select[name=\"ClientId\"]").SelectOptionAsync(new[] { dhClientId! }); + await page.Locator("select[name=\"ClientId\"]").ClickAsync(); // there is JS that runs on the click event, so simulate click here + await Task.Delay(2000); + // Arrange - Set CdrArrangementId + await page.Locator("select[name=\"CdrArrangementId\"]").SelectOptionAsync(new[] { cdrArrangement!.CDRArrangementID ?? throw new NullReferenceException(nameof(cdrArrangement.CDRArrangementID)) }); + // Arrange - Set Sharing Duration + await page.Locator("input[name=\"SharingDuration\"]").FillAsync(SHARING_DURATION); + + // Act - Click Initiate PAR button + await page.Locator("div.form >> text=Initiate PAR").ClickAsync(); + + // Act - Click request uri + await page.Locator("p.results > a").ClickAsync(); + + // Act/Assert - Perform consent and authorisation + await ConsentAndAuthorisation2(page, customerId, customerAccounts); + }); + } + finally + { + await CleanupAsync(async (page) => + { + try { await ClientRegistration_Delete(page); } catch { }; + try { await Consents_DeleteLocal(page); } catch { }; + }); + } + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + public async Task AC08_ConsumerDataSharing_Banking(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + try + { + string? dhClientId = null; + ConsentAndAuthorisationResponse? cdrArrangement = null; + await ArrangeAsync(async (page) => + { + await DataHolders_Discover(page, "ALL", "2", -1); // get all dh brands + await SSA_Get(page, "ALL", "3", drBrandId, drSoftwareProductId, "OK - SSA Generated"); + dhClientId = await ClientRegistration_Create(page, dhBrandId, drBrandId, drSoftwareProductId) + ?? throw new NullReferenceException(nameof(dhClientId)); + cdrArrangement = await ConsentAndAuthorisation(page, dhClientId, dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts); + }); + + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC08_ConsumerDataSharing_Banking)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Consumer Data Sharing - Banking").ClickAsync(); + await page.Locator("h2 >> text=Data Sharing - Banking").TextContentAsync(); + await Task.Delay(2000); // give screen time to refresh + }); + } + finally + { + await CleanupAsync(async (page) => + { + try { await ClientRegistration_Delete(page); } catch { }; + try { await Consents_DeleteLocal(page); } catch { }; + }); + } + } + + [Theory] + [InlineData(DH_BRANDID, DR_BRANDID, DR_SOFTWAREPRODUCTID, CUSTOMERID_BANKING, CUSTOMERACCOUNTS_BANKING)] + public async Task AC08_ConsumerDataSharing_Banking_AccountsGet(string dhBrandId, string drBrandId, string drSoftwareProductId, string customerId, string customerAccounts) + { + try + { + string? dhClientId = null; + ConsentAndAuthorisationResponse? cdrArrangement = null; + await ArrangeAsync(async (page) => + { + await DataHolders_Discover(page, "ALL", "2", -1); // get all dh brands + await SSA_Get(page, "ALL", "3", drBrandId, drSoftwareProductId, "OK - SSA Generated"); + dhClientId = await ClientRegistration_Create(page, dhBrandId, drBrandId, drSoftwareProductId) + ?? throw new NullReferenceException(nameof(dhClientId)); + cdrArrangement = await ConsentAndAuthorisation(page, dhClientId, dhBrandId, drBrandId, drSoftwareProductId, customerId, customerAccounts) + ?? throw new NullReferenceException(nameof(cdrArrangement)); + }); + + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC08_ConsumerDataSharing_Banking_AccountsGet)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Consumer Data Sharing - Banking").ClickAsync(); + await page.Locator("h2 >> text=Data Sharing - Banking").TextContentAsync(); + + // Arrange - Get Swagger iframe + var iFrame = page.FrameByUrl($"{WEB_URL}/{SWAGGER_BANKING_IFRAME}") ?? throw new Exception($"IFrame not found - {SWAGGER_BANKING_IFRAME}"); + + // Wait for the CDR arrangement to be added and populated. + System.Threading.Thread.Sleep(10000); + + // Arrange - Select CDR arrangemment + await iFrame.SelectOptionAsync( + "select", + new string[] { + cdrArrangement!.CDRArrangementID ?? throw new NullReferenceException(nameof(cdrArrangement.CDRArrangementID)) + }, + new FrameSelectOptionOptions() { Timeout = 90000 } + ); + + // Arrange - Click GET​/energy​/accountsGet Energy Accounts + await iFrame.ClickAsync("text=GET​/energy​/accountsGet Energy Accounts"); + + // Arrange - Click Try it out + await iFrame.ClickAsync("text=Try it out"); + + // Arrange - Set x-v + await iFrame.FillAsync("[placeholder=\"x-v\"]", "1"); + + // Act - Click Execute + await iFrame.ClickAsync("text=Execute"); + + // Assert - Status code should be 200 + var statusCode = await iFrame.Locator("div.responses-inner > div > div > table > tbody > tr > td.response-col_status").TextContentAsync(); + statusCode.Should().Be("200"); + }); + } + finally + { + await CleanupAsync(async (page) => + { + try { await ClientRegistration_Delete(page); } catch { }; + try { await Consents_DeleteLocal(page); } catch { }; + }); + } + } + + [Theory] + [InlineData(IDTOKEN)] + public async Task AC09_IDTokenHelper(string encryptedToken) + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC09_IDTokenHelper)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=ID Token Helper").ClickAsync(); + await page.Locator("h2 >> text=ID Token Helper").TextContentAsync(); + + // Arrange - Enter id token to decrypt + await page.Locator("textarea[name=\"IdTokenEncrypted\"]").FillAsync(encryptedToken); + + // Act + await page.Locator("text=Decrypt ID Token").ClickAsync(); + + // Assert - Check results + await TestResults(page, "nbf", "1653444726"); + await TestResults(page, "exp", "1653445026"); + // await TestResults(page, "iss", $"https://{BaseTest.HOSTNAME_DATAHOLDER}:8001"); + await TestResults(page, "iss", $"https://localhost:8001"); // token is const, it was created on localhost, we are just checking the decryption of token works and not where it was issued + await TestResults(page, "aud", "17d9e269-96d7-4b2a-bd0d-6767ecff965a"); + await TestResults(page, "nonce", "78b2faa4-954c-45de-af0e-33d1424732c7"); + await TestResults(page, "iat", "1653444725"); + await TestResults(page, "at_hash", "jybXQh-TiklHgnSjITgtoA"); + await TestResults(page, "s_hash", "DlHToSN2VJtaskuOQYV2sw"); + await TestResults(page, "auth_time", "1653444711"); + await TestResults(page, "idp", "local"); + await TestResults(page, "cdr_arrangement_id", "d6505b4b-001c-4b98-ae36-1b4d29ea0ef4"); + await TestResults(page, "sub", "mYnxnN7keNe/eiR2j9OZ+axM5WUUa5IdTUEBxyqQWUToZbS9MlaxYYPEhWOhJUQl"); + await TestResults(page, "name", "Kamilla Smith"); + await TestResults(page, "family_name", "Smith"); + await TestResults(page, "given_name", "Kamilla"); + await TestResults(page, "updated_at", "1614623400"); + await TestResults(page, "acr", "urn:cds.au:cdr:2"); + await TestResults(page, "amr", "pwd"); + }); + } + + [Fact] + public async Task AC10_PrivateKeyJWTGenerator() + { + // await ArrangeAsync(async () => { }); + + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC10_PrivateKeyJWTGenerator)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Private Key JWT Generator").ClickAsync(); + await page.Locator("h2 >> text=Private Key JWT Generator").TextContentAsync(); + await page.Locator("input[name=\"Jti\"]").FillAsync("foo"); + + // Act - Click generate button + await page.Locator("form >> text=Generate").ClickAsync(); + + // Assert - Client assertion was generated, and check for View Decoded button + var clientAssertion = await page.Locator("div.results >> div.code").TextContentAsync(); + clientAssertion.Should().NotBeNullOrWhiteSpace(); + await page.Locator("a >> text=View Decoded").TextContentAsync(); + + // Assert - Check client assertions claims + await TestResults(page, "sub", "c6327f87-687a-4369-99a4-eaacd3bb8210"); + await TestResults(page, "jti", "foo"); + await TestResults(page, "iat"); // just check claim exists + await TestResults(page, "exp"); // just check claim exists + await TestResults(page, "iss", "c6327f87-687a-4369-99a4-eaacd3bb8210"); + await TestResults(page, "aud", $"https://{BaseTest_v2.HOSTNAME_REGISTER}:7001/idp/connect/token"); + }); + } + + [Fact] + public async Task AC11_Settings() + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC11_Settings)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=Settings").ClickAsync(); + await page.Locator("h2 >> text=Settings").TextContentAsync(); + }); + } + + [Fact] + public async Task AC12_About() + { + await TestAsync($"{nameof(US23863_MDR_E2ETests_v2)} - {nameof(AC12_About)}", async (page) => + { + // Arrange - Goto home page, click menu button, check page loaded + await page.GotoAsync(WEB_URL); + await page.Locator("a >> text=About").ClickAsync(); + await page.Locator("h2 >> text=About").TextContentAsync(); + }); + } + } +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/appsettings.Container.json b/Source/CDR.DataRecipient.E2ETests/appsettings.Container.json new file mode 100644 index 0000000..c1d530b --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/appsettings.Container.json @@ -0,0 +1,25 @@ +{ + "ConnectionStrings": { + "DataHolder": "Server=mssql;Database=cdr-mdh;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True", + "DataHolderEnergy": "Server=mssql;Database=cdr-mdhe;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True", + "DataHolderIdentityServer": "Server=mssql;Database=cdr-idsvr;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True", + "DataHolderEnergyIdentityServer": "Server=mssql;Database=cdr-idsvre;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True", + "Register": "Server=mssql;Database=cdr-register;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True", + "DataRecipient": "Server=mssql;Database=cdr-mdr;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True" + }, + "Web_URL": "https://mock-data-recipient:9001", + "Hostnames": { + "Register": "mock-register", + "DataHolder": "mock-data-holder", + "DataHolderEnergy": "mock-data-holder-energy", + "DataRecipient": "mock-data-recipient" + }, + "CreateMedia": false, + "MediaFolder": "/testresults/media", + "DataHolder": { + "AccessTokenLifetimeSeconds": 3600 + }, + "TLS_BaseURL": "https://mock-register:7000", + "MTLS_BaseURL": "https://mock-register:7001", + "Admin_BaseURL": "https://mock-register:7006" +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/appsettings.Development.json b/Source/CDR.DataRecipient.E2ETests/appsettings.Development.json new file mode 100644 index 0000000..01dfffc --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/appsettings.Development.json @@ -0,0 +1,25 @@ +{ + "ConnectionStrings": { + "DataHolder": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-mdh;Integrated Security=true", + "DataHolderEnergy": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-mdhe;Integrated Security=true", + "DataHolderIdentityServer": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-idsvr;Integrated Security=true", + "DataHolderEnergyIdentityServer": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-idsvre;Integrated Security=true", + "Register": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-register;Integrated Security=true", + "DataRecipient": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-mdr;Integrated Security=true" + }, + "Web_URL": "https://localhost:9001", + "CreateMedia": false, + "MediaFolder": "C:\\cdr\\Media", + "Hostnames": { + "Register": "localhost", + "DataHolder": "localhost", + "DataHolderEnergy": "localhost", + "DataRecipient": "localhost" + }, + "DataHolder": { + "AccessTokenLifetimeSeconds": 300 + }, + "TLS_BaseURL": "https://localhost:7000", + "MTLS_BaseURL": "https://localhost:7001", + "Admin_BaseURL": "https://localhost:7006" +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/appsettings.Pipeline.json b/Source/CDR.DataRecipient.E2ETests/appsettings.Pipeline.json deleted file mode 100644 index bb1dff1..0000000 --- a/Source/CDR.DataRecipient.E2ETests/appsettings.Pipeline.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "ConnectionStrings": { - "DataHolder": "Data Source=D:\\a\\mock-data-holder\\mock-data-holder\\cdr\\mdh.db", - "DataHolderIdentityServer": "Data Source=D:\\a\\mock-data-holder\\mock-data-holder\\cdr\\idsvr.db", - "Register": "Data Source=D:\\a\\mock-register\\mock-register\\cdr\\cdr.db", - "DataRecipient": "Data Source=D:\\a\\mock-data-recipient\\mock-data-recipient\\cdr\\mdr.db" - }, - "MediaFolder": "D:\\a\\mock-data-recipient\\mock-data-recipient\\cdr\\Media\\", - "DataHolder": { - "AccessTokenLifetimeSeconds": 3600 - } -} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/appsettings.Release.json b/Source/CDR.DataRecipient.E2ETests/appsettings.Release.json new file mode 100644 index 0000000..9d94b08 --- /dev/null +++ b/Source/CDR.DataRecipient.E2ETests/appsettings.Release.json @@ -0,0 +1,25 @@ +{ + "ConnectionStrings": { + "DataHolder": "Server=mssql;Database=cdr-mdh;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True;Encrypt=False", + "DataHolderEnergy": "Server=mssql;Database=cdr-mdhe;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True;Encrypt=False", + "DataHolderIdentityServer": "Server=mssql;Database=cdr-idsvr;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True;Encrypt=False", + "DataHolderEnergyIdentityServer": "Server=mssql;Database=cdr-idsvre;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True;Encrypt=False", + "Register": "Server=mssql;Database=cdr-register;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True;Encrypt=False", + "DataRecipient": "Server=mssql;Database=cdr-mdr;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True;Encrypt=False" + }, + "Web_URL": "https://mock-data-recipient:9001", + "CreateMedia": true, + "Hostnames": { + "Register": "mock-register", + "DataHolder": "mock-data-holder", + "DataHolderEnergy": "mock-data-holder-energy", + "DataRecipient": "mock-data-recipient" + }, + "MediaFolder": "/testresults/media", + "DataHolder": { + "AccessTokenLifetimeSeconds": 3600 + }, + "TLS_BaseURL": "https://mock-register:7000", + "MTLS_BaseURL": "https://mock-register:7001", + "Admin_BaseURL": "https://mock-register:7006" +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/appsettings.json b/Source/CDR.DataRecipient.E2ETests/appsettings.json index fa36dbf..f31bce4 100644 --- a/Source/CDR.DataRecipient.E2ETests/appsettings.json +++ b/Source/CDR.DataRecipient.E2ETests/appsettings.json @@ -1,12 +1,25 @@ { - "ConnectionStrings": { - "DataHolder": "Data Source=C:\\cdr\\mdh.db", - "DataHolderIdentityServer": "Data Source=C:\\cdr\\idsvr.db", - "Register": "Data Source=C:\\cdr\\cdr.db", - "DataRecipient": "Data Source=C:\\cdr\\mdr.db" - }, - "MediaFolder": "C:\\cdr\\Media", - "DataHolder": { - "AccessTokenLifetimeSeconds": 300 - } + "ConnectionStrings": { + "DataHolder": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-mdh;Integrated Security=true", + "DataHolderEnergy": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-mdhe;Integrated Security=true", + "DataHolderIdentityServer": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-idsvr;Integrated Security=true", + "DataHolderEnergyIdentityServer": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-idsvre;Integrated Security=true", + "Register": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-register;Integrated Security=true", + "DataRecipient": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-mdr;Integrated Security=true" + }, + "TestTimeout": 30000, + "Web_URL": "https://localhost:9001", + "CreateMedia": false, + "MediaFolder": "C:\\cdr\\Media", + "Hostnames": { + "Register": "localhost", + "DataHolder": "localhost", + "DataRecipient": "localhost" + }, + "DataHolder": { + "AccessTokenLifetimeSeconds": 300 + }, + "TLS_BaseURL": "https://localhost:7000", + "MTLS_BaseURL": "https://localhost:7001", + "Admin_BaseURL": "https://localhost:7006" } \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/e2e.runsettings b/Source/CDR.DataRecipient.E2ETests/e2e.runsettings index 77f23c5..b3eef4e 100644 --- a/Source/CDR.DataRecipient.E2ETests/e2e.runsettings +++ b/Source/CDR.DataRecipient.E2ETests/e2e.runsettings @@ -2,6 +2,6 @@ - Pipeline + Release \ No newline at end of file diff --git a/Source/CDR.DataRecipient.E2ETests/run-tests.bat b/Source/CDR.DataRecipient.E2ETests/run-tests.bat deleted file mode 100644 index 10b8161..0000000 --- a/Source/CDR.DataRecipient.E2ETests/run-tests.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -cls -echo Run tests? -pause -dotnet test --logger "console;verbosity=detailed" > _temp/20.log \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/BaseTest.cs b/Source/CDR.DataRecipient.IntegrationTests/BaseTest.cs index c4c285e..eab8db1 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/BaseTest.cs +++ b/Source/CDR.DataRecipient.IntegrationTests/BaseTest.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Net.Http; using System.Net.Http.Headers; +using System.Reflection; using System.Security.Claims; using System.Threading.Tasks; using CDR.DataRecipient.IntegrationTests.Extensions; @@ -11,47 +12,67 @@ using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using Xunit; +using Xunit.Sdk; #nullable enable namespace CDR.DataRecipient.IntegrationTests { + class DisplayTestMethodNameAttribute : BeforeAfterTestAttribute + { + static int count = 0; + + public override void Before(MethodInfo methodUnderTest) + { + Console.WriteLine($"Test #{++count} - {methodUnderTest.DeclaringType?.Name}.{methodUnderTest.Name}"); + } + + public override void After(MethodInfo methodUnderTest) + { + } + } + // Put all tests in same collection because we need them to run sequentially since some tests are mutating DB. [Collection("IntegrationTests")] [TestCaseOrderer("CDR.DataRecipient.IntegrationTests.XUnit.Orderers.AlphabeticalOrderer", "CDR.DataRecipient.IntegrationTests")] + [DisplayTestMethodName] abstract public class BaseTest { // Register - public const string REGISTER_MTLS_TOKEN_URL = "https://localhost:7001/idp/connect/token"; // Register Token API - public const string REGISTER_MTLS_DATAHOLDERBRANDS_URL = "https://localhost:7001/cdr-register/v1/banking/data-holders/brands"; + public static string REGISTER_MTLS_TOKEN_URL => $"https://{HOSTNAME_REGISTER}:7001/idp/connect/token"; // Register Token API + public static string REGISTER_MTLS_DATAHOLDERBRANDS_URL => $"https://{HOSTNAME_REGISTER}:7001/cdr-register/v1/banking/data-holders/brands"; public const string CLIENTASSERTIONTYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; // Data recipient - public const string CERTIFICATE_FILENAME = "certificates\\client.pfx"; + public const string CERTIFICATE_FILENAME = "Certificates/client.pfx"; public const string CERTIFICATE_PASSWORD = "#M0ckDataRecipient#"; - public const string JWT_CERTIFICATE_FILENAME = "certificates\\jwks.pfx"; + public const string JWT_CERTIFICATE_FILENAME = "Certificates/jwks.pfx"; public const string JWT_CERTIFICATE_PASSWORD = "#M0ckDataRecipient#"; + public const string SOFTWAREPRODUCT_ID = "C6327F87-687A-4369-99A4-EAACD3BB8210"; - public const string DATARECIPIENT_ARRANGEMENTS_REVOKE_URL = @"https://localhost:9001/arrangements/revoke"; + + public static string DATARECIPIENT_ARRANGEMENTS_REVOKE_URL => $"https://{HOSTNAME_DATARECIPIENT}:9001/arrangements/revoke"; // Data holder - public const string DATAHOLDER_CERTIFICATE_FILENAME = "certificates\\mock-data-holder-server.pfx"; + public const string DATAHOLDER_CERTIFICATE_FILENAME = "Certificates/mock-data-holder-server.pfx"; public const string DATAHOLDER_CERTIFICATE_PASSWORD = "#M0ckDataHolder#"; public const string DATAHOLDER_BRAND = "804FC2FB-18A7-4235-9A49-2AF393D18BC7"; // Bank 1 - public const string DATAHOLDER_BRAND_INFOSECBASEURL = "https://localhost:8001"; - - // // Mongo - // public const string MONGODB_CONNECTIONSTRING = "mongodb://localhost:27017"; - // public const string MONGODB_DATABASENAME = "mdr"; - // public const string MONGODB_DATAHOLDERBRANDS_COLLECTIONNAME = "data-holder-brands"; - // public const string MONGODB_CDRARRANGEMENTS_COLLECTIONNAME = "cdr-arrangements"; + public static string DATAHOLDER_BRAND_INFOSECBASEURL => $"https://{HOSTNAME_DATAHOLDER}:8001"; - // SQLite connection strings + // SQL connection strings static public string REGISTER_CONNECTIONSTRING => Configuration["ConnectionStrings:Register"] ?? throw new Exception($"{nameof(REGISTER_CONNECTIONSTRING)} - configuration setting not found"); static public string DATARECIPIENT_CONNECTIONSTRING => Configuration["ConnectionStrings:DataRecipient"] ?? throw new Exception($"{nameof(DATARECIPIENT_CONNECTIONSTRING)} - configuration setting not found"); + // Hostnames + static public string HOSTNAME_REGISTER => Configuration["Hostnames:Register"] + ?? throw new Exception($"{nameof(HOSTNAME_REGISTER)} - configuration setting not found"); + static public string HOSTNAME_DATAHOLDER => Configuration["Hostnames:DataHolder"] + ?? throw new Exception($"{nameof(HOSTNAME_DATAHOLDER)} - configuration setting not found"); + static public string HOSTNAME_DATARECIPIENT => Configuration["Hostnames:DataRecipient"] + ?? throw new Exception($"{nameof(HOSTNAME_DATARECIPIENT)} - configuration setting not found"); + static private IConfigurationRoot? configuration; static public IConfigurationRoot Configuration { diff --git a/Source/CDR.DataRecipient.IntegrationTests/CDR.DataRecipient.IntegrationTests.csproj b/Source/CDR.DataRecipient.IntegrationTests/CDR.DataRecipient.IntegrationTests.csproj index e87d537..495d8b9 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/CDR.DataRecipient.IntegrationTests.csproj +++ b/Source/CDR.DataRecipient.IntegrationTests/CDR.DataRecipient.IntegrationTests.csproj @@ -1,64 +1,81 @@ - + - - net5.0 + + net6.0 - false - + false - - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - + 0.2.0 - - - + 0.2.0 - - - + 0.2.0 + - - - Always - - - Always - - - Always - - - Always - - - Always - - + + + + + - - - Always - - - Always - - + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + Always + + + Always + + + Always + + + Always + + diff --git a/Source/CDR.DataRecipient.IntegrationTests/Certificates/client.pfx b/Source/CDR.DataRecipient.IntegrationTests/Certificates/client.pfx index cfc2626..85e022e 100644 Binary files a/Source/CDR.DataRecipient.IntegrationTests/Certificates/client.pfx and b/Source/CDR.DataRecipient.IntegrationTests/Certificates/client.pfx differ diff --git a/Source/CDR.DataRecipient.IntegrationTests/Certificates/jwks.pfx b/Source/CDR.DataRecipient.IntegrationTests/Certificates/jwks.pfx index 099e908..d5fb751 100644 Binary files a/Source/CDR.DataRecipient.IntegrationTests/Certificates/jwks.pfx and b/Source/CDR.DataRecipient.IntegrationTests/Certificates/jwks.pfx differ diff --git a/Source/CDR.DataRecipient.IntegrationTests/Certificates/mock-data-holder-server.pfx b/Source/CDR.DataRecipient.IntegrationTests/Certificates/mock-data-holder-server.pfx index 3ada383..d9f2efc 100644 Binary files a/Source/CDR.DataRecipient.IntegrationTests/Certificates/mock-data-holder-server.pfx and b/Source/CDR.DataRecipient.IntegrationTests/Certificates/mock-data-holder-server.pfx differ diff --git a/Source/CDR.DataRecipient.IntegrationTests/Certificates/mock-data-holder.pfx b/Source/CDR.DataRecipient.IntegrationTests/Certificates/mock-data-holder.pfx index 6ab1d13..b836450 100644 Binary files a/Source/CDR.DataRecipient.IntegrationTests/Certificates/mock-data-holder.pfx and b/Source/CDR.DataRecipient.IntegrationTests/Certificates/mock-data-holder.pfx differ diff --git a/Source/CDR.DataRecipient.IntegrationTests/Extensions/JsonExtensions.cs b/Source/CDR.DataRecipient.IntegrationTests/Extensions/JsonExtensions.cs index 380fe0d..3b6688b 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/Extensions/JsonExtensions.cs +++ b/Source/CDR.DataRecipient.IntegrationTests/Extensions/JsonExtensions.cs @@ -29,12 +29,6 @@ public static string JsonStripComments(this string json) /// public static bool JsonCompare(this string json, string jsonToCompare) { - //var jsonObject = JsonSerializer.Deserialize(json); - //var jsonToCompareObject = JsonSerializer.Deserialize(jsonToCompare); - //var jsonNormalised = JsonSerializer.Serialize(jsonObject); - //var jsonToCompareNormalised = JsonSerializer.Serialize(jsonToCompareObject); - //return jsonNormalised == jsonToCompareNormalised; - var jsonToken = JToken.Parse(json); var jsonToCompareToken = JToken.Parse(jsonToCompare); return JToken.DeepEquals(jsonToken, jsonToCompareToken); diff --git a/Source/CDR.DataRecipient.IntegrationTests/Extensions/SqlExtensions.cs b/Source/CDR.DataRecipient.IntegrationTests/Extensions/SqlExtensions.cs new file mode 100644 index 0000000..65de9ac --- /dev/null +++ b/Source/CDR.DataRecipient.IntegrationTests/Extensions/SqlExtensions.cs @@ -0,0 +1,69 @@ +using Microsoft.Data.SqlClient; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Data; + +namespace CDR.DataRecipient.IntegrationTests.Extensions +{ + static public class SqlExtensions + { + /// + /// Execute scalar command and return result as Int32. Throw error if no results or conversion error + /// + static public Int32 ExecuteScalarInt32(this SqlCommand command) + { + var res = command.ExecuteScalar(); + + if (res == DBNull.Value || res == null) + { + throw new Exception("Command returns no results"); + } + + return Convert.ToInt32(res); + } + + /// + /// Execute scalar command and return result as string. Throw error if no results or conversion error + /// + static public string ExecuteScalarString(this SqlCommand command) + { + var res = command.ExecuteScalar(); + + if (res == DBNull.Value || res == null) + { + throw new Exception("Command returns no results"); + } + + return Convert.ToString(res); + } + + /// + /// Execute command and return result as json. + /// + public static string ExecuteJson(this SqlCommand cmd) + { + using (DataTable dt = new DataTable()) + { + using (SqlDataAdapter da = new SqlDataAdapter(cmd)) + { + da.Fill(dt); + + List> rows = new List>(); + Dictionary row; + foreach (DataRow dr in dt.Rows) + { + row = new Dictionary(); + foreach (DataColumn col in dt.Columns) + { + row.Add(col.ColumnName, dr[col]); + } + rows.Add(row); + } + + return JsonConvert.SerializeObject(new { rows }); + } + } + } + } +} diff --git a/Source/CDR.DataRecipient.IntegrationTests/Fixtures/TestSetup.cs b/Source/CDR.DataRecipient.IntegrationTests/Fixtures/TestSetup.cs new file mode 100644 index 0000000..4456002 --- /dev/null +++ b/Source/CDR.DataRecipient.IntegrationTests/Fixtures/TestSetup.cs @@ -0,0 +1,38 @@ +using Microsoft.Data.SqlClient; + +namespace CDR.DataRecipient.IntegrationTests.Fixtures +{ + internal static class TestSetup + { + public static void PatchRegister() + { + using var connection = new SqlConnection(BaseTest.REGISTER_CONNECTIONSTRING); + connection.Open(); + + using var updateCommand = new SqlCommand($@" + update + softwareproduct + set + recipientbaseuri = 'https://{BaseTest.HOSTNAME_DATARECIPIENT}:9001', + revocationuri = 'https://{BaseTest.HOSTNAME_DATARECIPIENT}:9001/revocation', + redirecturis = 'https://{BaseTest.HOSTNAME_DATARECIPIENT}:9001/consent/callback', + jwksuri = 'https://{BaseTest.HOSTNAME_DATARECIPIENT}:9001/jwks' + where + softwareproductid = 'C6327F87-687A-4369-99A4-EAACD3BB8210'", + connection); + updateCommand.ExecuteNonQuery(); + + using var updateCommand2 = new SqlCommand($@" + update + endpoint + set + publicbaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER}:8000', + resourcebaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER}:8002', + infosecbaseuri = 'https://{BaseTest.HOSTNAME_DATAHOLDER}:8001' + where + brandid = '804FC2FB-18A7-4235-9A49-2AF393D18BC7'", + connection); + updateCommand2.ExecuteNonQuery(); + } + } +} diff --git a/Source/CDR.DataRecipient.IntegrationTests/ForPipeline/seed-data.json b/Source/CDR.DataRecipient.IntegrationTests/ForPipeline/seed-data.json deleted file mode 100644 index dd33cd7..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/ForPipeline/seed-data.json +++ /dev/null @@ -1,1820 +0,0 @@ -{ - "LegalEntities": [ - { - "LegalEntityId": "18b75a76-5821-4c9e-b465-4709291cf0f4", - "LegalEntityName": "Mock Software Company", - "LogoUri": "https://mocksoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "11222333444", - "Acn": "222333444", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000099", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "ffb1c8ba-279e-44d8-96f0-1bc34a6b436f", - "BrandName": "Mock Finance Tools", - "LogoUri": "https://mocksoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "c6327f87-687a-4369-99a4-eaacd3bb8210", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "MyBudgetHelper", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://mocksoftware/mybudgetapp/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://mocksoftware/mybudgetapp", - "TosUri": "https://mocksoftware/mybudgetapp/terms", - "PolicyUri": "https://mocksoftware/mybudgetapp/policy", - "RecipientBaseUri": "https://localhost:9001", - "RevocationUri": "https://localhost:9001/revocation", - "RedirectUris": "https://localhost:9001/consent/callback", - "JwksUri": "https://localhost:9001/jwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "de815a93-85b3-4fe8-9513-33ad8f4359d0", - "LegalEntityName": "yoyo Software Company", - "LogoUri": "https://yoyosoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "11222333444", - "Acn": "222333444", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000005", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "f3f0c40b-9df8-491a-af1d-81cb9ab5f021", - "BrandName": "YoYo", - "LogoUri": "https://yoyosoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "6f7a1b8e-8799-48a8-9011-e3920391f713", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "MyBudgetHelper", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://yoyosoftware/mybudgetapp/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://yoyosoftware/mybudgetapp", - "TosUri": "https://yoyosoftware/mybudgetapp/terms", - "PolicyUri": "https://yoyosoftware/mybudgetapp/policy", - "RecipientBaseUri": "https://api.yoyosoftware/mybudgetapp", - "RevocationUri": "https://api.yoyosoftware/mybudgetapp/revoke", - "RedirectUris": "https://api.yoyosoftware/mybudgetapp/callback https://api.yoyosoftware/mybudgetapp/return", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "a1ca85da-7be8-4020-9c27-c9623eca582b", - "LegalEntityName": "Xray Software Pty Ltd", - "LogoUri": "https://xraysoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "112341234", - "Acn": "12341243", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000006", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "fe123396-4eba-4518-aade-b245ceea78af", - "BrandName": "XRay Financial", - "LogoUri": "https://xraysoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "6a25c22b-0810-4f41-8e41-f48d162c517d", - "SoftwareProductName": "Budget direct", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://xraysoftware/budgetdirect/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://xraysoftware/budgetdirect", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://api.xrayoftware/budgetdirect", - "RevocationUri": "https://api.xraysoftware/budgetdirect/revoke", - "RedirectUris": "https://api.xraysoftware/budgetdirect/callback", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "8ff78c90-74c2-4c51-9c04-9d829476687a", - "LegalEntityName": "WOW Software Company", - "LogoUri": "https://wowsoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "88778877", - "Acn": "99889988", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000007", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "8fe9791a-e4a8-4104-b1cb-e0df41189520", - "BrandName": "WOW", - "LogoUri": "https://wowsoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-02-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "9788e6d3-75a1-47eb-a891-dd752ced0f61", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "MyBudgetHelper", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://wowsoftware/mybudgetapp/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://wowsoftware/mybudgetapp", - "TosUri": "https://wowsoftware/mybudgetapp/terms", - "PolicyUri": "https://wowsoftware/mybudgetapp/policy", - "RecipientBaseUri": "https://api.wowsoftware/mybudgetapp", - "RevocationUri": "https://api.wowsoftware/mybudgetapp/revoke", - "RedirectUris": "https://api.wowsoftware/mybudgetapp/callback https://api.mocksoftware/mybudgetapp/return", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "4a29856c-2634-4fea-bf9b-74c99c337e2f", - "LegalEntityName": "olm Software Company", - "LogoUri": "https://olmsoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "88778877", - "Acn": "99889988", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000008", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "a7171ba3-fd05-456f-a859-be4e1cbcc17d", - "BrandName": "OLM Software", - "LogoUri": "https://olmsoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "05d7dfd7-1d8f-4abf-b987-cf56c9115e8d", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "Budgeter", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://olmsoftware/mybudgetapp/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://olmsoftware/mybudgetapp", - "TosUri": "https://olmsoftware/mybudgetapp/terms", - "PolicyUri": "https://olmsoftware/mybudgetapp/policy", - "RecipientBaseUri": "https://api.olmsoftware/mybudgetapp", - "RevocationUri": "https://api.olmsoftware/mybudgetapp/revoke", - "RedirectUris": "https://api.olmsoftware/mybudgetapp/redirect", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "f138d974-0d12-4150-ad0f-c77af745c60b", - "LegalEntityName": "xlogical Software Company", - "LogoUri": "https://xlogical/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": null, - "Acn": null, - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001009", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "8a3441aa-1242-493a-b466-dcbfffe5a441", - "BrandName": "xlogical", - "LogoUri": "https://xlogical/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "25ee528f-35ac-4a66-a67c-6166602c9322", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "Loan Calculator ", - "SoftwareProductDescription": "Loan applications", - "LogoUri": "https://xlogical/products/loancalculator/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://xlogical/products/loancalculator", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://xlogical/products/loancalculator", - "RevocationUri": "https://xlogical/products/loancalculator/revocation", - "RedirectUris": "https://xlogical/products/loancalculator/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "8c31bb93-9469-4094-979a-8530a85a6aa1", - "LegalEntityName": "Non-tech Software Company", - "LogoUri": "https://nontech/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "98765987654", - "Acn": "987659876", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001010", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "fb88befe-b1d1-4b18-8182-78d4130eaa0c", - "BrandName": "Non-tech", - "LogoUri": "https://nontech/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00" - } - ] - } - ] - }, - { - "LegalEntityId": "93ef5f28-7f30-43f2-8e5c-b1e3cb39ce90", - "LegalEntityName": "New Bank", - "LogoUri": "https://newbank/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "99888777666", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "6e9cfaf7-ecae-4de3-bbc5-ea9f366bdf55", - "BrandName": "New Bank", - "LogoUri": "https://newbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.newbank", - "ResourceBaseUri": "https://api.newbank", - "InfoSecBaseUri": "https://idp.newbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://newbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.newbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "e81ab637-b3b7-4403-82b8-a43077a569d6", - "LegalEntityName": "Royal Bank", - "LogoUri": "https://royalbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "94477558833", - "Acn": "99000033", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "a5252bde-d1a6-413f-8f53-f7e2f6ab3f77", - "BrandName": "Royal Bank", - "LogoUri": "https://royalbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-01T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.royalbank", - "ResourceBaseUri": "https://api.royalbank", - "InfoSecBaseUri": "https://idp.royalbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://royalbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.royalbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "e81ab636-b3b7-4403-82b8-a43077a569d6", - "LegalEntityName": "Central Bank", - "LogoUri": "https://centralbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "123981224123", - "Acn": "44123312", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "c1ff7731-5843-4384-88d8-6062afde7c5b", - "BrandName": "central bank", - "LogoUri": "https://centralbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-03-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.centralbank", - "ResourceBaseUri": "https://api.centralbank", - "InfoSecBaseUri": "https://idp.centralbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://centralbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.centralbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "aeca53ab-2a90-4737-938d-987ce195ca14", - "LegalEntityName": "Sun Bank", - "LogoUri": "https://sunbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "94477558899", - "Acn": "99000099", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "f6dfbe5b-c57a-4ec2-bc97-66c1f7fe6c1d", - "BrandName": "Sun", - "LogoUri": "https://sunbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-01T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.sunbank", - "ResourceBaseUri": "https://api.sunbank", - "InfoSecBaseUri": "https://idp.sunbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://sunbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.sunbank/jwks" - } - ] - }, - { - "BrandId": "a2cd9cd1-e3c7-493b-86d8-f9f319ca0732", - "BrandName": "Brighter Bank", - "LogoUri": "https://brighterbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-01-01T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.brighterbank", - "ResourceBaseUri": "https://api.brighterbank", - "InfoSecBaseUri": "https://idp.brighterbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://brighterbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.brighterbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "ba1311fb-5cea-4c5c-b4ed-f2a98a0915e0", - "LegalEntityName": "Hot Bank", - "LogoUri": "https://hotbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "12345678901", - "Acn": "123456789", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "62f4a113-defe-4f99-bd9c-625277bc0e36", - "BrandName": "mildBank", - "LogoUri": "https://mildbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-11T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.mildbank", - "ResourceBaseUri": "https://api.mildbank", - "InfoSecBaseUri": "https://idp.mildbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://mildbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://mildbank/idp/jwks" - } - ] - }, - { - "BrandId": "81d3d5cc-cdb6-4253-a78b-b17155dde7fd", - "BrandName": "extrahotBank", - "LogoUri": "https://extrahotbank/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-16T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.extrahotbank", - "ResourceBaseUri": "https://api.extrahotbank", - "InfoSecBaseUri": "https://idp.extrahotbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://extrahotbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://extrahotbank/idp/jwks" - } - ] - } - ] - } - ] - }, - - { - "LegalEntityId": "725c6e62-bfa7-4719-94af-415ae64d4bcd", - "LegalEntityName": "Ive Bank", - "LogoUri": "https://ivebank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "1231231239", - "Acn": "099800998", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "9928cf0f-70c7-40ea-b7ad-cad190232f68", - "BrandName": "Ive Bank", - "LogoUri": "https://ivebank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-03T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.ivebank", - "ResourceBaseUri": "https://api.ivebank", - "InfoSecBaseUri": "https://idp.ivebank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://ivebank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.ivebank/jwks" - } - ] - } - ] - } - ] - }, - - { - "LegalEntityId": "2f1c327f-56b6-40c5-8e2e-b2130867329c", - "LegalEntityName": "Eva Bank", - "LogoUri": "https://evabank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "98765456788765", - "Acn": "22121232", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "7c97c3b5-fe64-4b35-8ae0-17fa5d4aa0a8", - "BrandName": "Eva Bank corp", - "LogoUri": "https://evabankcorp/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-26T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.evabank", - "ResourceBaseUri": "https://api.evabank", - "InfoSecBaseUri": "https://idp.evabank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://evabank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.evabank/jwks" - } - ] - } - ] - } - ] - }, - - - { - "LegalEntityId": "ae4af466-54c6-4ce4-ad2d-580bc6496943", - "LegalEntityName": "Fox Bank", - "LogoUri": "https://foxbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "3123421245", - "Acn": "1223412123", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "2192a459-5ef5-4493-afe1-56c3d03fc1ba", - "BrandName": "Fox Bank", - "LogoUri": "https://foxbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-21T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.foxbank", - "ResourceBaseUri": "https://api.foxbank", - "InfoSecBaseUri": "https://idp.foxbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://foxbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.foxbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "017fcfc8-1fd3-4ef4-8f08-b697c4c681ee", - "LegalEntityName": "Grand Bank", - "LogoUri": "https://grandbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "99888777666", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "8aa8e9a6-1dc7-4428-baea-d1f4533428b9", - "BrandName": "Grand Bank", - "LogoUri": "https://grandbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-29T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.grandbank", - "ResourceBaseUri": "https://api.grandbank", - "InfoSecBaseUri": "https://idp.grandbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://grandbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.grandbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "7b1a7566-e113-411b-94b7-d3b9fb0da98a", - "LegalEntityName": "Kiss Bank", - "LogoUri": "https://kissbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "123477455", - "Acn": "1121222", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "85168ace-9211-45e3-bb75-f85c54e66f10", - "BrandName": "Kiss Bank", - "LogoUri": "https://kissbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-12T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.kissbank", - "ResourceBaseUri": "https://api.kissbank", - "InfoSecBaseUri": "https://idp.kissbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://kissbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.kissbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "667407fc-dc7e-4be5-8795-5189240bcbca", - "LegalEntityName": "Luna Bank", - "LogoUri": "https://lunabank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "12334412233", - "Acn": "77553322", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "bb03be60-5c46-422e-a27e-aefa0015078d", - "BrandName": "Luna", - "LogoUri": "https://lunabank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-12T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.lunabank", - "ResourceBaseUri": "https://api.lunabank", - "InfoSecBaseUri": "https://idp.lunabank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://lunabank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.lunabank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "7993c227-9252-432b-9b2f-a8666e2fd2f2", - "LegalEntityName": "Mu Bank", - "LogoUri": "https://mubank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "1352345345", - "Acn": "1121231231", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "52d23611-4493-4a21-9095-44ae9eb85841", - "BrandName": "Mu Bank", - "LogoUri": "https://mubank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.mubank", - "ResourceBaseUri": "https://api.mubank", - "InfoSecBaseUri": "https://idp.mubank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://mubank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.mubank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "9c7dec6d-2e46-4b53-8430-5337c7eb93e9", - "LegalEntityName": "Noon Bank", - "LogoUri": "https://noonbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "1112359979", - "Acn": "22443522", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "557f42e8-4e00-4b03-a9c9-d97796b6418b", - "BrandName": "Noon Bank", - "LogoUri": "https://noonbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.noonbank", - "ResourceBaseUri": "https://api.noonbank", - "InfoSecBaseUri": "https://idp.noonbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://noonbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.noonbank/jwks" - } - ] - } - ] - } - ] - }, - - { - "LegalEntityId": "b9b45c14-3346-47f7-ad78-3416762cf1d8", - "LegalEntityName": "Oppo Bank", - "LogoUri": "https://oppobank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "124124124", - "Acn": "9955433", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "a5e45351-d13c-4690-93d1-3da515e71a92", - "BrandName": "Oppo Bank", - "LogoUri": "https://oppobank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.oppobank", - "ResourceBaseUri": "https://api.oppobank", - "InfoSecBaseUri": "https://idp.oppobank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://oppobank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.oppobank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "b7a18659-eb9b-4130-a0df-402c85f1f216", - "LegalEntityName": "Pepper Bank", - "LogoUri": "https://pepperbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "8735652435", - "Acn": "32234234", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "97e53112-73b2-482a-b352-39d389d67916", - "BrandName": "Pepper Bank", - "LogoUri": "https://pepperbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.pepperbank", - "ResourceBaseUri": "https://api.pepperbank", - "InfoSecBaseUri": "https://idp.pepperbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://pepperbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.pepperbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "fe75814c-99ee-4922-a6b0-71913e60984c", - "LegalEntityName": "QQ Bank", - "LogoUri": "https://qqbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "21111244", - "Acn": "31231", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "895e54c5-93e0-405f-8072-0a9871bac8b5", - "BrandName": "QQ Bank", - "LogoUri": "https://qqbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.qqbank", - "ResourceBaseUri": "https://api.qqbank", - "InfoSecBaseUri": "https://idp.qqbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://qqbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.qqbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "06c595f2-f0b2-4684-90e1-6905e4537304", - "LegalEntityName": "Run Bank", - "LogoUri": "https://runbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "99888777666", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "975375f7-2bd9-44b5-a188-43d65ca8eaae", - "BrandName": "Run Bank", - "LogoUri": "https://runbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.runbank", - "ResourceBaseUri": "https://api.runbank", - "InfoSecBaseUri": "https://idp.runbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://runbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.runbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "350c4b28-132c-4248-a962-1434e00e7046", - "LegalEntityName": "SaS Bank", - "LogoUri": "https://sasbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "99888777666", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "b648f694-0dee-4f5e-bd2c-9837ac08fb7b", - "BrandName": "SaS Bank", - "LogoUri": "https://sasbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.sasbank", - "ResourceBaseUri": "https://api.sasbank", - "InfoSecBaseUri": "https://idp.sasbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://sasbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.sasbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "a1349224-adf3-4678-ba9b-f9ec800b5dc5", - "LegalEntityName": "TnT Bank", - "LogoUri": "https://tntbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "1312341243", - "Acn": "533211", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "f8bce914-ac8d-436a-b265-19baca6d1df2", - "BrandName": "TnT Bank", - "LogoUri": "https://tntbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.tntbank", - "ResourceBaseUri": "https://api.tntbank", - "InfoSecBaseUri": "https://idp.tntbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://tntbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.tntbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "0d332caa-8cd8-4ac9-8898-20641c54bc8c", - "LegalEntityName": "Bank Legal Entity 1", - "LogoUri": "https://bank/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "11111111111", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "804fc2fb-18a7-4235-9a49-2af393d18bc7", - "BrandName": "Bank Brand 1", - "LogoUri": "https://bank1/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://localhost:8000", - "ResourceBaseUri": "https://localhost:8002", - "InfoSecBaseUri": "https://localhost:8001", - "ExtensionBaseUri": "", - "WebsiteUri": "https://bank1/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.bank1/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "bc9d68f2-74c4-43d5-9a9c-93e72a2e84c9", - "LegalEntityName": "Bank Legal Entity 2", - "LogoUri": "https://bank2/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "11111111111", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "e748eadf-4aa4-4e2f-b3da-fb4a9d511994", - "BrandName": "Bank Brand 2", - "LogoUri": "https://bank2/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.bank2", - "ResourceBaseUri": "https://api.bank2", - "InfoSecBaseUri": "https://idp.bank2", - "ExtensionBaseUri": "", - "WebsiteUri": "https://bank2/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.bank1/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "3d974478-afa6-4ce4-80bc-6f93e8e92e19", - "LegalEntityName": "Smarter Bank", - "LogoUri": "https://smarterbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "12345678901", - "Acn": "123456789", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "9f8df3e2-6866-42af-91d4-5faa3204f0b8", - "BrandName": "Smarter Bank", - "LogoUri": "https://smarterbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.smarterbank", - "ResourceBaseUri": "https://api.smarterbank", - "InfoSecBaseUri": "https://idp.smarterbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://smarterbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://smarterbank/idp/jwks" - } - ] - }, - { - "BrandId": "81d3d5cb-cdb6-4253-a78b-b17155dde7fd", - "BrandName": "MyBank", - "LogoUri": "https://mybank/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.mybank", - "ResourceBaseUri": "https://api.mybank", - "InfoSecBaseUri": "https://idp.mybank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://mybank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://mybank/idp/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "924ca498-0f19-402d-ae07-2cb61088f8aa", - "LegalEntityName": "Hall Bank", - "LogoUri": "https://hallbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "12345678901", - "Acn": "123456789", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "cf217aba-e00d-48d5-9c3d-03af0b91cb80", - "BrandName": "Hall Bank", - "LogoUri": "https://hallardbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-19T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.hallbank", - "ResourceBaseUri": "https://api.hallbank", - "InfoSecBaseUri": "https://idp.hallbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://hallbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://hallbank/idp/jwks" - } - ] - }, - { - "BrandId": "920f296d-5f2f-49de-876c-15a4aa1b4a79", - "BrandName": "Hallway", - "LogoUri": "https://hallwaybank/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-18T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.hallwaybank", - "ResourceBaseUri": "https://api.hallwaybank", - "InfoSecBaseUri": "https://idp.hallwaybank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://hallwaybank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://hallwaybank/idp/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "04361651-f485-421a-8e3e-d01dd7ab2706", - "LegalEntityName": "Job Bank", - "LogoUri": "https://jobbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "13254365476", - "Acn": "264352", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "bc144967-d6f8-47a6-8590-07caf522141b", - "BrandName": "Jobs Bank", - "LogoUri": "https://jobsbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.jobsbank", - "ResourceBaseUri": "https://api.jobsbank", - "InfoSecBaseUri": "https://idp.jobsbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://jobsbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://jobsbank/idp/jwks" - } - ] - }, - { - "BrandId": "7b47ecf8-a991-4dd3-adef-b89564005e8e", - "BrandName": "offer bank", - "LogoUri": "https://offerbank/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.offerbank", - "ResourceBaseUri": "https://api.offerbank", - "InfoSecBaseUri": "https://idp.offerbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://offerbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://offerbank/idp/jwks" - } - ] - }, - { - "BrandId": "c3176245-4258-4383-b945-cd2f7c828d3c", - "BrandName": "J bank", - "LogoUri": "https://jbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-18T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.jbank", - "ResourceBaseUri": "https://api.jbank", - "InfoSecBaseUri": "https://idp.jbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://jbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://jbank/idp/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "9d34ede4-2c76-4ecc-a31e-ea8392d31cc9", - "LegalEntityName": "FintechX", - "LogoUri": "https://fintechx/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "98765987654", - "Acn": "987659876", - "Arbn": null, - "IndustryCode": null, - "OrganisationTypeId": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001001", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "20c0864b-ceef-4de0-8944-eb0962f825eb", - "BrandName": "Finance X", - "LogoUri": "https://fintechx/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "d3c44426-e003-4604-aa45-4137e45dfbc4", - "SoftwareProductName": "Loan Calculator X", - "SoftwareProductDescription": "Loan affordability application", - "LogoUri": "https://fintechx/products/loancalculator/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://fintechx/products/loancalculator", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://fintechx/products/loancalculator", - "RevocationUri": "https://fintechx/products/loancalculator/revocation", - "RedirectUris": "https://fintechx/products/loancalculator/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "9381dad2-6b68-4879-b496-c1319d7dfbc9", - "SoftwareProductName": "Track Xpense", - "SoftwareProductDescription": "Application to allow you to track your expenses", - "LogoUri": "https://fintechx/products/trackxpense/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://fintechx/products/trackxpense", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://fintechx/products/trackxpense", - "RevocationUri": "https://fintechx/products/trackxpense/revoke", - "RedirectUris": "https://fintechx/products/trackxpense/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "63bc22ac-6fd2-4e85-a979-c2fc7c4db9da", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "TestProductCert", - "SoftwareProductDescription": "Application to allow you to track your expenses", - "LogoUri": "https://fintechx/products/trackxpense/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://fintechx/products/trackxpense", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://fintechx/products/trackxpense", - "RevocationUri": "https://fintechx/products/trackxpense/revoke", - "RedirectUris": "https://fintechx/products/trackxpense/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "86ecb655-9eba-409c-9be3-59e7adf7080d", - "SoftwareProductName": "MockDataRecepient", - "SoftwareProductDescription": "Mock Data Recepient", - "LogoUri": "https://fintechx/products/trackxpense/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://fintechx/products/trackxpense", - "TosUri": "https://fintechx/products/trackxpense/tos", - "PolicyUri": "https://fintechx/products/trackxpense/policy", - "RecipientBaseUri": "https://fintechx/products/trackxpense", - "RevocationUri": "https://fintechx/products/trackxpense/revoke", - "RedirectUris": "https://fintechx/products/trackxpense/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "f72ab707-a619-4dc1-a90b-177d61bcf574", - "LegalEntityName": "HotFinTech", - "LogoUri": "https://hotfintech/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "01944123445", - "Acn": "123412345", - "Arbn": null, - "IndustryCode": null, - "OrganisationTypeId": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001002", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "46b33515-b4a5-4b1c-b5b4-25654d675be6", - "BrandName": "HotFinTech", - "LogoUri": "https://hotfintech/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-05T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "d3c44425-e003-4604-aa45-4137e45dfbc4", - "SoftwareProductName": "Pay advance", - "SoftwareProductDescription": "Buy first and pay later product", - "LogoUri": "https://hotfintech/products/payadvance/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://hotfintech/products/payadvance ", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://hotfintech/products/payadvance", - "RevocationUri": "https://hotfintech/products/payadvance/revocation", - "RedirectUris": "https://hotfintech/products/payadvance/redirect", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "9926a894-cc29-4d63-b3b4-e404066ae6f2", - "SoftwareProductName": "Track sheet", - "SoftwareProductDescription": "Application to allow you to track your expenses", - "LogoUri": "https://hotfintech/products/tracksheet/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://hotfintech/products/tracksheet/", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://hotfintech/products/tracksheet", - "RevocationUri": "https://hotfintech/products/tracksheet/revoke", - "RedirectUris": "https://hotfintech/products/tracksheet/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "c70456f3-843f-4407-a988-577c108a7816", - "LegalEntityName": "ZeroFintech", - "LogoUri": "https://zerofintech/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "98765987654", - "Acn": "987659876", - "Arbn": null, - "IndustryCode": null, - "OrganisationTypeId": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001004", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "ebbcc2f2-817e-42b8-8a28-cd45902159e0", - "BrandName": "ZeroFintech", - "LogoUri": "https://zerofintech/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-05T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "5d03d1a6-b83b-4176-a2f4-d0074a205695", - "SoftwareProductName": "Mortgage", - "SoftwareProductDescription": "calculate the mortgage value", - "LogoUri": "https://zerofintech/products/mortgage/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://zerofintech/products/mortgage", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://zerofintech/products/mortgage", - "RevocationUri": "https://zerofintech/products/mortgage/revocation", - "RedirectUris": "https://zerofintech/products/mortgage/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "dafa09db-4433-4203-907a-bdf797c8cd21", - "SoftwareProductName": "Reward program", - "SoftwareProductDescription": "Application to allow you to track your expenses", - "LogoUri": "https://zerofintech//products/rewards/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://zerofintech/products/rewards", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://zerofintech/products/rewards", - "RevocationUri": "https://hotfintech/products/rewards/revoke", - "RedirectUris": "https://zerofintech/products/rewards/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/admin-api/appsettings.Production.json b/Source/CDR.DataRecipient.IntegrationTests/ForRegister/admin-api/appsettings.Production.json deleted file mode 100644 index 9e539d5..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/admin-api/appsettings.Production.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "IdentityServerTokenUri": "https://mock-register:7001/idp/connect/token", - - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "SeedData": { - "FilePath": "Data/seed-data.json", - "OverwriteExistingData": false - }, - "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], - "MinimumLevel": "Debug", - "WriteTo": [ - { "Name": "Console" }, - { - "Name": "File", - "Args": { "path": "/tmp/cdr-mr-admin-api.log" } - } - ], - "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ], - "Properties": { - "Application": "CDR.Register.Admin.API" - } - }, - "ConnectionStrings": { - "DefaultConnection": "Data Source=/tmp/CDR.db" - } -} diff --git a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/discovery-api/appsettings.Production.json b/Source/CDR.DataRecipient.IntegrationTests/ForRegister/discovery-api/appsettings.Production.json deleted file mode 100644 index 8d8a066..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/discovery-api/appsettings.Production.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "IdentityServerUrl": "https://mock-register:7000/idp", - "IdentityServerIssuer": "https://mock-register:7000/idp", - - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], - "MinimumLevel": "Debug", - "WriteTo": [ - { "Name": "Console" }, - { - "Name": "File", - "Args": { "path": "/tmp/cdr-mr-discovery-api.log" } - } - ], - "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ], - "Properties": { - "Application": "CDR.Register.Discovery.API" - } - }, - "ConnectionStrings": { - "DefaultConnection": "Data Source=/tmp/CDR.db" - } -} diff --git a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/idsvr/appsettings.Production.json b/Source/CDR.DataRecipient.IntegrationTests/ForRegister/idsvr/appsettings.Production.json deleted file mode 100644 index b1c97ee..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/idsvr/appsettings.Production.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "IssuerUri": "https://mock-register:7000/idp", - "JwksUri": "https://mock-register:7000/idp/.well-known/openid-configuration/jwks", - "TokenUri": "https://mock-register:7001/idp/connect/token", - - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], - "MinimumLevel": "Debug", - "WriteTo": [ - { "Name": "Console" }, - { - "Name": "File", - "Args": { "path": "/tmp/cdr-mr-identityserver.log" } - } - ], - "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ], - "Properties": { - "Application": "CDR.Register.IdentityServer" - } - }, - "ConnectionStrings": { - "DefaultConnection": "Data Source=/tmp/CDR.db" - } -} diff --git a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/readme.md b/Source/CDR.DataRecipient.IntegrationTests/ForRegister/readme.md deleted file mode 100644 index 65798ef..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/readme.md +++ /dev/null @@ -1 +0,0 @@ -This files in this folder need replace the corresponding files in the OSR for Mock Register. \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/seed-data.json b/Source/CDR.DataRecipient.IntegrationTests/ForRegister/seed-data.json deleted file mode 100644 index 715a500..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/seed-data.json +++ /dev/null @@ -1,1820 +0,0 @@ -{ - "LegalEntities": [ - { - "LegalEntityId": "18b75a76-5821-4c9e-b465-4709291cf0f4", - "LegalEntityName": "Mock Software Company", - "LogoUri": "https://mocksoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "11222333444", - "Acn": "222333444", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000099", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "ffb1c8ba-279e-44d8-96f0-1bc34a6b436f", - "BrandName": "Mock Finance Tools", - "LogoUri": "https://mocksoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "c6327f87-687a-4369-99a4-eaacd3bb8210", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "MyBudgetHelper", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://mocksoftware/mybudgetapp/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://mocksoftware/mybudgetapp", - "TosUri": "https://mocksoftware/mybudgetapp/terms", - "PolicyUri": "https://mocksoftware/mybudgetapp/policy", - "RecipientBaseUri": "https://mock-data-recipient:9001", - "RevocationUri": "https://mock-data-recipient:9001/revocation", - "RedirectUris": "https://mock-data-recipient:9001/consent/callback", - "JwksUri": "https://mock-data-recipient:9001/jwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "de815a93-85b3-4fe8-9513-33ad8f4359d0", - "LegalEntityName": "yoyo Software Company", - "LogoUri": "https://yoyosoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "11222333444", - "Acn": "222333444", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000005", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "f3f0c40b-9df8-491a-af1d-81cb9ab5f021", - "BrandName": "YoYo", - "LogoUri": "https://yoyosoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "6f7a1b8e-8799-48a8-9011-e3920391f713", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "MyBudgetHelper", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://yoyosoftware/mybudgetapp/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://yoyosoftware/mybudgetapp", - "TosUri": "https://yoyosoftware/mybudgetapp/terms", - "PolicyUri": "https://yoyosoftware/mybudgetapp/policy", - "RecipientBaseUri": "https://api.yoyosoftware/mybudgetapp", - "RevocationUri": "https://api.yoyosoftware/mybudgetapp/revoke", - "RedirectUris": "https://api.yoyosoftware/mybudgetapp/callback https://api.yoyosoftware/mybudgetapp/return", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "a1ca85da-7be8-4020-9c27-c9623eca582b", - "LegalEntityName": "Xray Software Pty Ltd", - "LogoUri": "https://xraysoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "112341234", - "Acn": "12341243", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000006", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "fe123396-4eba-4518-aade-b245ceea78af", - "BrandName": "XRay Financial", - "LogoUri": "https://xraysoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "6a25c22b-0810-4f41-8e41-f48d162c517d", - "SoftwareProductName": "Budget direct", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://xraysoftware/budgetdirect/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://xraysoftware/budgetdirect", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://api.xrayoftware/budgetdirect", - "RevocationUri": "https://api.xraysoftware/budgetdirect/revoke", - "RedirectUris": "https://api.xraysoftware/budgetdirect/callback", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "8ff78c90-74c2-4c51-9c04-9d829476687a", - "LegalEntityName": "WOW Software Company", - "LogoUri": "https://wowsoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "88778877", - "Acn": "99889988", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000007", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "8fe9791a-e4a8-4104-b1cb-e0df41189520", - "BrandName": "WOW", - "LogoUri": "https://wowsoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-02-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "9788e6d3-75a1-47eb-a891-dd752ced0f61", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "MyBudgetHelper", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://wowsoftware/mybudgetapp/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://wowsoftware/mybudgetapp", - "TosUri": "https://wowsoftware/mybudgetapp/terms", - "PolicyUri": "https://wowsoftware/mybudgetapp/policy", - "RecipientBaseUri": "https://api.wowsoftware/mybudgetapp", - "RevocationUri": "https://api.wowsoftware/mybudgetapp/revoke", - "RedirectUris": "https://api.wowsoftware/mybudgetapp/callback https://api.mocksoftware/mybudgetapp/return", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "4a29856c-2634-4fea-bf9b-74c99c337e2f", - "LegalEntityName": "olm Software Company", - "LogoUri": "https://olmsoftware/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "88778877", - "Acn": "99889988", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK000008", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "a7171ba3-fd05-456f-a859-be4e1cbcc17d", - "BrandName": "OLM Software", - "LogoUri": "https://olmsoftware/img/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "05d7dfd7-1d8f-4abf-b987-cf56c9115e8d", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "Budgeter", - "SoftwareProductDescription": "A product to help you manage your budget", - "LogoUri": "https://olmsoftware/mybudgetapp/img/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://olmsoftware/mybudgetapp", - "TosUri": "https://olmsoftware/mybudgetapp/terms", - "PolicyUri": "https://olmsoftware/mybudgetapp/policy", - "RecipientBaseUri": "https://api.olmsoftware/mybudgetapp", - "RevocationUri": "https://api.olmsoftware/mybudgetapp/revoke", - "RedirectUris": "https://api.olmsoftware/mybudgetapp/redirect", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "f138d974-0d12-4150-ad0f-c77af745c60b", - "LegalEntityName": "xlogical Software Company", - "LogoUri": "https://xlogical/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": null, - "Acn": null, - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001009", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "8a3441aa-1242-493a-b466-dcbfffe5a441", - "BrandName": "xlogical", - "LogoUri": "https://xlogical/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "25ee528f-35ac-4a66-a67c-6166602c9322", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "Loan Calculator ", - "SoftwareProductDescription": "Loan applications", - "LogoUri": "https://xlogical/products/loancalculator/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://xlogical/products/loancalculator", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://xlogical/products/loancalculator", - "RevocationUri": "https://xlogical/products/loancalculator/revocation", - "RedirectUris": "https://xlogical/products/loancalculator/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "8c31bb93-9469-4094-979a-8530a85a6aa1", - "LegalEntityName": "Non-tech Software Company", - "LogoUri": "https://nontech/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "98765987654", - "Acn": "987659876", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001010", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "fb88befe-b1d1-4b18-8182-78d4130eaa0c", - "BrandName": "Non-tech", - "LogoUri": "https://nontech/logo.png", - "BrandStatusId": 1, // Map internally - "LastUpdated": "2021-04-06T11:58:00" - } - ] - } - ] - }, - { - "LegalEntityId": "93ef5f28-7f30-43f2-8e5c-b1e3cb39ce90", - "LegalEntityName": "New Bank", - "LogoUri": "https://newbank/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "99888777666", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "6e9cfaf7-ecae-4de3-bbc5-ea9f366bdf55", - "BrandName": "New Bank", - "LogoUri": "https://newbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.newbank", - "ResourceBaseUri": "https://api.newbank", - "InfoSecBaseUri": "https://idp.newbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://newbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.newbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "e81ab637-b3b7-4403-82b8-a43077a569d6", - "LegalEntityName": "Royal Bank", - "LogoUri": "https://royalbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "94477558833", - "Acn": "99000033", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "a5252bde-d1a6-413f-8f53-f7e2f6ab3f77", - "BrandName": "Royal Bank", - "LogoUri": "https://royalbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-01T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.royalbank", - "ResourceBaseUri": "https://api.royalbank", - "InfoSecBaseUri": "https://idp.royalbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://royalbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.royalbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "e81ab636-b3b7-4403-82b8-a43077a569d6", - "LegalEntityName": "Central Bank", - "LogoUri": "https://centralbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "123981224123", - "Acn": "44123312", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "c1ff7731-5843-4384-88d8-6062afde7c5b", - "BrandName": "central bank", - "LogoUri": "https://centralbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-03-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.centralbank", - "ResourceBaseUri": "https://api.centralbank", - "InfoSecBaseUri": "https://idp.centralbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://centralbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.centralbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "aeca53ab-2a90-4737-938d-987ce195ca14", - "LegalEntityName": "Sun Bank", - "LogoUri": "https://sunbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "94477558899", - "Acn": "99000099", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "f6dfbe5b-c57a-4ec2-bc97-66c1f7fe6c1d", - "BrandName": "Sun", - "LogoUri": "https://sunbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-01T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.sunbank", - "ResourceBaseUri": "https://api.sunbank", - "InfoSecBaseUri": "https://idp.sunbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://sunbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.sunbank/jwks" - } - ] - }, - { - "BrandId": "a2cd9cd1-e3c7-493b-86d8-f9f319ca0732", - "BrandName": "Brighter Bank", - "LogoUri": "https://brighterbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-01-01T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.brighterbank", - "ResourceBaseUri": "https://api.brighterbank", - "InfoSecBaseUri": "https://idp.brighterbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://brighterbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.brighterbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "ba1311fb-5cea-4c5c-b4ed-f2a98a0915e0", - "LegalEntityName": "Hot Bank", - "LogoUri": "https://hotbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "12345678901", - "Acn": "123456789", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "62f4a113-defe-4f99-bd9c-625277bc0e36", - "BrandName": "mildBank", - "LogoUri": "https://mildbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-11T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.mildbank", - "ResourceBaseUri": "https://api.mildbank", - "InfoSecBaseUri": "https://idp.mildbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://mildbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://mildbank/idp/jwks" - } - ] - }, - { - "BrandId": "81d3d5cc-cdb6-4253-a78b-b17155dde7fd", - "BrandName": "extrahotBank", - "LogoUri": "https://extrahotbank/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-16T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.extrahotbank", - "ResourceBaseUri": "https://api.extrahotbank", - "InfoSecBaseUri": "https://idp.extrahotbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://extrahotbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://extrahotbank/idp/jwks" - } - ] - } - ] - } - ] - }, - - { - "LegalEntityId": "725c6e62-bfa7-4719-94af-415ae64d4bcd", - "LegalEntityName": "Ive Bank", - "LogoUri": "https://ivebank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "1231231239", - "Acn": "099800998", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "9928cf0f-70c7-40ea-b7ad-cad190232f68", - "BrandName": "Ive Bank", - "LogoUri": "https://ivebank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-03T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.ivebank", - "ResourceBaseUri": "https://api.ivebank", - "InfoSecBaseUri": "https://idp.ivebank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://ivebank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.ivebank/jwks" - } - ] - } - ] - } - ] - }, - - { - "LegalEntityId": "2f1c327f-56b6-40c5-8e2e-b2130867329c", - "LegalEntityName": "Eva Bank", - "LogoUri": "https://evabank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "98765456788765", - "Acn": "22121232", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "7c97c3b5-fe64-4b35-8ae0-17fa5d4aa0a8", - "BrandName": "Eva Bank corp", - "LogoUri": "https://evabankcorp/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-26T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.evabank", - "ResourceBaseUri": "https://api.evabank", - "InfoSecBaseUri": "https://idp.evabank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://evabank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.evabank/jwks" - } - ] - } - ] - } - ] - }, - - - { - "LegalEntityId": "ae4af466-54c6-4ce4-ad2d-580bc6496943", - "LegalEntityName": "Fox Bank", - "LogoUri": "https://foxbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "3123421245", - "Acn": "1223412123", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "2192a459-5ef5-4493-afe1-56c3d03fc1ba", - "BrandName": "Fox Bank", - "LogoUri": "https://foxbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-21T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.foxbank", - "ResourceBaseUri": "https://api.foxbank", - "InfoSecBaseUri": "https://idp.foxbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://foxbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.foxbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "017fcfc8-1fd3-4ef4-8f08-b697c4c681ee", - "LegalEntityName": "Grand Bank", - "LogoUri": "https://grandbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "99888777666", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "8aa8e9a6-1dc7-4428-baea-d1f4533428b9", - "BrandName": "Grand Bank", - "LogoUri": "https://grandbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-29T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.grandbank", - "ResourceBaseUri": "https://api.grandbank", - "InfoSecBaseUri": "https://idp.grandbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://grandbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.grandbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "7b1a7566-e113-411b-94b7-d3b9fb0da98a", - "LegalEntityName": "Kiss Bank", - "LogoUri": "https://kissbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "123477455", - "Acn": "1121222", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "85168ace-9211-45e3-bb75-f85c54e66f10", - "BrandName": "Kiss Bank", - "LogoUri": "https://kissbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-12T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.kissbank", - "ResourceBaseUri": "https://api.kissbank", - "InfoSecBaseUri": "https://idp.kissbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://kissbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.kissbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "667407fc-dc7e-4be5-8795-5189240bcbca", - "LegalEntityName": "Luna Bank", - "LogoUri": "https://lunabank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "12334412233", - "Acn": "77553322", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "bb03be60-5c46-422e-a27e-aefa0015078d", - "BrandName": "Luna", - "LogoUri": "https://lunabank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-12T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.lunabank", - "ResourceBaseUri": "https://api.lunabank", - "InfoSecBaseUri": "https://idp.lunabank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://lunabank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.lunabank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "7993c227-9252-432b-9b2f-a8666e2fd2f2", - "LegalEntityName": "Mu Bank", - "LogoUri": "https://mubank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "1352345345", - "Acn": "1121231231", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "52d23611-4493-4a21-9095-44ae9eb85841", - "BrandName": "Mu Bank", - "LogoUri": "https://mubank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.mubank", - "ResourceBaseUri": "https://api.mubank", - "InfoSecBaseUri": "https://idp.mubank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://mubank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.mubank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "9c7dec6d-2e46-4b53-8430-5337c7eb93e9", - "LegalEntityName": "Noon Bank", - "LogoUri": "https://noonbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "1112359979", - "Acn": "22443522", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "557f42e8-4e00-4b03-a9c9-d97796b6418b", - "BrandName": "Noon Bank", - "LogoUri": "https://noonbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.noonbank", - "ResourceBaseUri": "https://api.noonbank", - "InfoSecBaseUri": "https://idp.noonbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://noonbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.noonbank/jwks" - } - ] - } - ] - } - ] - }, - - { - "LegalEntityId": "b9b45c14-3346-47f7-ad78-3416762cf1d8", - "LegalEntityName": "Oppo Bank", - "LogoUri": "https://oppobank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "124124124", - "Acn": "9955433", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "a5e45351-d13c-4690-93d1-3da515e71a92", - "BrandName": "Oppo Bank", - "LogoUri": "https://oppobank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.oppobank", - "ResourceBaseUri": "https://api.oppobank", - "InfoSecBaseUri": "https://idp.oppobank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://oppobank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.oppobank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "b7a18659-eb9b-4130-a0df-402c85f1f216", - "LegalEntityName": "Pepper Bank", - "LogoUri": "https://pepperbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "8735652435", - "Acn": "32234234", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "97e53112-73b2-482a-b352-39d389d67916", - "BrandName": "Pepper Bank", - "LogoUri": "https://pepperbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.pepperbank", - "ResourceBaseUri": "https://api.pepperbank", - "InfoSecBaseUri": "https://idp.pepperbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://pepperbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.pepperbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "fe75814c-99ee-4922-a6b0-71913e60984c", - "LegalEntityName": "QQ Bank", - "LogoUri": "https://qqbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "21111244", - "Acn": "31231", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "895e54c5-93e0-405f-8072-0a9871bac8b5", - "BrandName": "QQ Bank", - "LogoUri": "https://qqbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.qqbank", - "ResourceBaseUri": "https://api.qqbank", - "InfoSecBaseUri": "https://idp.qqbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://qqbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.qqbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "06c595f2-f0b2-4684-90e1-6905e4537304", - "LegalEntityName": "Run Bank", - "LogoUri": "https://runbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "99888777666", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "975375f7-2bd9-44b5-a188-43d65ca8eaae", - "BrandName": "Run Bank", - "LogoUri": "https://runbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.runbank", - "ResourceBaseUri": "https://api.runbank", - "InfoSecBaseUri": "https://idp.runbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://runbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.runbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "350c4b28-132c-4248-a962-1434e00e7046", - "LegalEntityName": "SaS Bank", - "LogoUri": "https://sasbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "99888777666", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "b648f694-0dee-4f5e-bd2c-9837ac08fb7b", - "BrandName": "SaS Bank", - "LogoUri": "https://sasbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.sasbank", - "ResourceBaseUri": "https://api.sasbank", - "InfoSecBaseUri": "https://idp.sasbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://sasbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.sasbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "a1349224-adf3-4678-ba9b-f9ec800b5dc5", - "LegalEntityName": "TnT Bank", - "LogoUri": "https://tntbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "1312341243", - "Acn": "533211", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "f8bce914-ac8d-436a-b265-19baca6d1df2", - "BrandName": "TnT Bank", - "LogoUri": "https://tntbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-09T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.tntbank", - "ResourceBaseUri": "https://api.tntbank", - "InfoSecBaseUri": "https://idp.tntbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://tntbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.tntbank/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "0d332caa-8cd8-4ac9-8898-20641c54bc8c", - "LegalEntityName": "Bank Legal Entity 1", - "LogoUri": "https://bank/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "11111111111", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "804fc2fb-18a7-4235-9a49-2af393d18bc7", - "BrandName": "Bank Brand 1", - "LogoUri": "https://bank1/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://mock-data-holder:8000", - "ResourceBaseUri": "https://mock-data-holder:8002", - "InfoSecBaseUri": "https://mock-data-holder:8001", - "ExtensionBaseUri": "", - "WebsiteUri": "https://bank1/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.bank1/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "bc9d68f2-74c4-43d5-9a9c-93e72a2e84c9", - "LegalEntityName": "Bank Legal Entity 2", - "LogoUri": "https://bank2/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "11111111111", - "Acn": "888777666", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "e748eadf-4aa4-4e2f-b3da-fb4a9d511994", - "BrandName": "Bank Brand 2", - "LogoUri": "https://bank2/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.bank2", - "ResourceBaseUri": "https://api.bank2", - "InfoSecBaseUri": "https://idp.bank2", - "ExtensionBaseUri": "", - "WebsiteUri": "https://bank2/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://idp.bank1/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "3d974478-afa6-4ce4-80bc-6f93e8e92e19", - "LegalEntityName": "Smarter Bank", - "LogoUri": "https://smarterbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "12345678901", - "Acn": "123456789", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "9f8df3e2-6866-42af-91d4-5faa3204f0b8", - "BrandName": "Smarter Bank", - "LogoUri": "https://smarterbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.smarterbank", - "ResourceBaseUri": "https://api.smarterbank", - "InfoSecBaseUri": "https://idp.smarterbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://smarterbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://smarterbank/idp/jwks" - } - ] - }, - { - "BrandId": "81d3d5cb-cdb6-4253-a78b-b17155dde7fd", - "BrandName": "MyBank", - "LogoUri": "https://mybank/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.mybank", - "ResourceBaseUri": "https://api.mybank", - "InfoSecBaseUri": "https://idp.mybank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://mybank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://mybank/idp/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "924ca498-0f19-402d-ae07-2cb61088f8aa", - "LegalEntityName": "Hall Bank", - "LogoUri": "https://hallbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "12345678901", - "Acn": "123456789", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "cf217aba-e00d-48d5-9c3d-03af0b91cb80", - "BrandName": "Hall Bank", - "LogoUri": "https://hallardbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-19T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.hallbank", - "ResourceBaseUri": "https://api.hallbank", - "InfoSecBaseUri": "https://idp.hallbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://hallbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://hallbank/idp/jwks" - } - ] - }, - { - "BrandId": "920f296d-5f2f-49de-876c-15a4aa1b4a79", - "BrandName": "Hallway", - "LogoUri": "https://hallwaybank/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-18T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.hallwaybank", - "ResourceBaseUri": "https://api.hallwaybank", - "InfoSecBaseUri": "https://idp.hallwaybank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://hallwaybank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://hallwaybank/idp/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "04361651-f485-421a-8e3e-d01dd7ab2706", - "LegalEntityName": "Job Bank", - "LogoUri": "https://jobbank/img/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "13254365476", - "Acn": "264352", - "Arbn": null, - "IndustryCode": null, - "OrganisationType": null, - "AccreditationNumber": null, - "Participations": [ - { - "ParticipationTypeId": 1, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "bc144967-d6f8-47a6-8590-07caf522141b", - "BrandName": "Jobs Bank", - "LogoUri": "https://jobsbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.jobsbank", - "ResourceBaseUri": "https://api.jobsbank", - "InfoSecBaseUri": "https://idp.jobsbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://jobsbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://jobsbank/idp/jwks" - } - ] - }, - { - "BrandId": "7b47ecf8-a991-4dd3-adef-b89564005e8e", - "BrandName": "offer bank", - "LogoUri": "https://offerbank/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.offerbank", - "ResourceBaseUri": "https://api.offerbank", - "InfoSecBaseUri": "https://idp.offerbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://offerbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://offerbank/idp/jwks" - } - ] - }, - { - "BrandId": "c3176245-4258-4383-b945-cd2f7c828d3c", - "BrandName": "J bank", - "LogoUri": "https://jbank/img/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-18T11:58:00", - "Endpoint": { - "Version": 1, - "PublicBaseUri": "https://publicapi.jbank", - "ResourceBaseUri": "https://api.jbank", - "InfoSecBaseUri": "https://idp.jbank", - "ExtensionBaseUri": "", - "WebsiteUri": "https://jbank/" - }, - "AuthDetails": [ - { - "RegisterUTypeId": 1, - "JwksEndpoint": "https://jbank/idp/jwks" - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "9d34ede4-2c76-4ecc-a31e-ea8392d31cc9", - "LegalEntityName": "FintechX", - "LogoUri": "https://fintechx/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "98765987654", - "Acn": "987659876", - "Arbn": null, - "IndustryCode": null, - "OrganisationTypeId": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001001", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "20c0864b-ceef-4de0-8944-eb0962f825eb", - "BrandName": "Finance X", - "LogoUri": "https://fintechx/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-06T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "d3c44426-e003-4604-aa45-4137e45dfbc4", - "SoftwareProductName": "Loan Calculator X", - "SoftwareProductDescription": "Loan affordability application", - "LogoUri": "https://fintechx/products/loancalculator/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://fintechx/products/loancalculator", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://fintechx/products/loancalculator", - "RevocationUri": "https://fintechx/products/loancalculator/revocation", - "RedirectUris": "https://fintechx/products/loancalculator/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "9381dad2-6b68-4879-b496-c1319d7dfbc9", - "SoftwareProductName": "Track Xpense", - "SoftwareProductDescription": "Application to allow you to track your expenses", - "LogoUri": "https://fintechx/products/trackxpense/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://fintechx/products/trackxpense", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://fintechx/products/trackxpense", - "RevocationUri": "https://fintechx/products/trackxpense/revoke", - "RedirectUris": "https://fintechx/products/trackxpense/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "63bc22ac-6fd2-4e85-a979-c2fc7c4db9da", // Optional - SoftwareProductName is unique within a Brand - "SoftwareProductName": "TestProductCert", - "SoftwareProductDescription": "Application to allow you to track your expenses", - "LogoUri": "https://fintechx/products/trackxpense/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://fintechx/products/trackxpense", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://fintechx/products/trackxpense", - "RevocationUri": "https://fintechx/products/trackxpense/revoke", - "RedirectUris": "https://fintechx/products/trackxpense/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "86ecb655-9eba-409c-9be3-59e7adf7080d", - "SoftwareProductName": "MockDataRecepient", - "SoftwareProductDescription": "Mock Data Recepient", - "LogoUri": "https://fintechx/products/trackxpense/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://fintechx/products/trackxpense", - "TosUri": "https://fintechx/products/trackxpense/tos", - "PolicyUri": "https://fintechx/products/trackxpense/policy", - "RecipientBaseUri": "https://fintechx/products/trackxpense", - "RevocationUri": "https://fintechx/products/trackxpense/revoke", - "RedirectUris": "https://fintechx/products/trackxpense/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "f72ab707-a619-4dc1-a90b-177d61bcf574", - "LegalEntityName": "HotFinTech", - "LogoUri": "https://hotfintech/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "01944123445", - "Acn": "123412345", - "Arbn": null, - "IndustryCode": null, - "OrganisationTypeId": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001002", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "46b33515-b4a5-4b1c-b5b4-25654d675be6", - "BrandName": "HotFinTech", - "LogoUri": "https://hotfintech/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-05T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "d3c44425-e003-4604-aa45-4137e45dfbc4", - "SoftwareProductName": "Pay advance", - "SoftwareProductDescription": "Buy first and pay later product", - "LogoUri": "https://hotfintech/products/payadvance/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://hotfintech/products/payadvance ", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://hotfintech/products/payadvance", - "RevocationUri": "https://hotfintech/products/payadvance/revocation", - "RedirectUris": "https://hotfintech/products/payadvance/redirect", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "9926a894-cc29-4d63-b3b4-e404066ae6f2", - "SoftwareProductName": "Track sheet", - "SoftwareProductDescription": "Application to allow you to track your expenses", - "LogoUri": "https://hotfintech/products/tracksheet/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://hotfintech/products/tracksheet/", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://hotfintech/products/tracksheet", - "RevocationUri": "https://hotfintech/products/tracksheet/revoke", - "RedirectUris": "https://hotfintech/products/tracksheet/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - }, - { - "LegalEntityId": "c70456f3-843f-4407-a988-577c108a7816", - "LegalEntityName": "ZeroFintech", - "LogoUri": "https://zerofintech/logo.png", - "RegistrationNumber": null, - "RegistrationDate": null, - "RegisteredCountry": null, - "Abn": "98765987654", - "Acn": "987659876", - "Arbn": null, - "IndustryCode": null, - "OrganisationTypeId": null, - "OrganisationType": null, - "AccreditationNumber": "ADRBNK001004", - "Participations": [ - { - "ParticipationTypeId": 2, - "IndustryId": 1, - "StatusId": 1, - "Brands": [ - { - "BrandId": "ebbcc2f2-817e-42b8-8a28-cd45902159e0", - "BrandName": "ZeroFintech", - "LogoUri": "https://zerofintech/logo.png", - "BrandStatusId": 1, - "LastUpdated": "2021-04-05T11:58:00", - "SoftwareProducts": [ - { - "SoftwareProductId": "5d03d1a6-b83b-4176-a2f4-d0074a205695", - "SoftwareProductName": "Mortgage", - "SoftwareProductDescription": "calculate the mortgage value", - "LogoUri": "https://zerofintech/products/mortgage/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://zerofintech/products/mortgage", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://zerofintech/products/mortgage", - "RevocationUri": "https://zerofintech/products/mortgage/revocation", - "RedirectUris": "https://zerofintech/products/mortgage/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - }, - { - "SoftwareProductId": "dafa09db-4433-4203-907a-bdf797c8cd21", - "SoftwareProductName": "Reward program", - "SoftwareProductDescription": "Application to allow you to track your expenses", - "LogoUri": "https://zerofintech//products/rewards/logo.png", - "SectorIdentifierUri": null, - "ClientUri": "https://zerofintech/products/rewards", - "TosUri": null, - "PolicyUri": null, - "RecipientBaseUri": "https://zerofintech/products/rewards", - "RevocationUri": "https://hotfintech/products/rewards/revoke", - "RedirectUris": "https://zerofintech/products/rewards/cb", - "JwksUri": "https://localhost:7006/loopback/MockDataRecipientJwks", - "Scope": "openid profile bank:accounts.basic:read bank:accounts.detail:read bank:transactions:read bank:payees:read bank:regular_payments:read common:customer.basic:read common:customer.detail:read cdr:registration", - "StatusId": 1, - "Certificates": [ - { - "CommonName": "MockDataRecipient", - "Thumbprint": "58D76F7A61CD726DA1C54F6898E8E69EA4C88060" - } - ] - } - ] - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/ssa-api/appsettings.Production.json b/Source/CDR.DataRecipient.IntegrationTests/ForRegister/ssa-api/appsettings.Production.json deleted file mode 100644 index 3ae48f0..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/ForRegister/ssa-api/appsettings.Production.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "IdentityServerUrl": "https://mock-register:7000/idp", - "IdentityServerIssuer": "https://mock-register:7000/idp", - - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], - "MinimumLevel": "Debug", - "WriteTo": [ - { "Name": "Console" }, - { - "Name": "File", - "Args": { "path": "/tmp/cdr-mr-ssa-api.log" } - } - ], - "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ], - "Properties": { - "Application": "CDR.Register.SSA.API" - } - }, - "ConnectionStrings": { - "DefaultConnection": "Data Source=/tmp/CDR.db" - } -} diff --git a/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/AccessToken.cs b/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/AccessToken.cs index 054eb08..d6f6baf 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/AccessToken.cs +++ b/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/AccessToken.cs @@ -13,8 +13,8 @@ namespace CDR.DataRecipient.IntegrationTests.Infrastructure { public class AccessToken { - private const string IDENTITYSERVER_URL = BaseTest.REGISTER_MTLS_TOKEN_URL; - private const string AUDIENCE = IDENTITYSERVER_URL; + private static readonly string IDENTITYSERVER_URL = BaseTest.REGISTER_MTLS_TOKEN_URL; + private static readonly string AUDIENCE = IDENTITYSERVER_URL; private const string SCOPE = "bank:accounts.basic:read"; private const string GRANT_TYPE = ""; private const string CLIENT_ID = "86ecb655-9eba-409c-9be3-59e7adf7080d"; @@ -76,11 +76,6 @@ static string BuildContent(string scope, string grant_type, string client_id, st return kvp.Value; } - // DEBUG - 07/09/2021 - // var tokenizer = new PrivateKeyJwt(certificateFilename, certificatePassword); - //var tokenizer = new CDR.DataHolder.IntegrationTests.Infrastructure.API3.PrivateKeyJwt(certificateFilename, certificatePassword); - // var client_assertion = tokenizer.Generate(issuer, audience); - var client_assertion = new PrivateKeyJwt2 { CertificateFilename = jwt_certificateFilename, @@ -89,7 +84,6 @@ static string BuildContent(string scope, string grant_type, string client_id, st Audience = audience }.Generate(); - // var request = new HttpRequestMessage(HttpMethod.Post, IDENTITYSERVER_URL) var request = new HttpRequestMessage(HttpMethod.Post, url) { Content = new StringContent( @@ -125,7 +119,6 @@ static string BuildContent(string scope, string grant_type, string client_id, st // Create an access token request var request = CreateAccessTokenRequest( URL, - // CertificateFilename, CertificatePassword, JWT_CertificateFilename ?? throw new Exception("JWT_Certificatefilename is null"), JWT_CertificatePassword, Issuer, Audience, @@ -135,8 +128,8 @@ static string BuildContent(string scope, string grant_type, string client_id, st var response = await client.SendAsync(request); if (response.StatusCode != HttpStatusCode.OK) - { - throw new Exception($"{nameof(AccessToken)}.{nameof(GetAsync)} - Error getting access token - {response.StatusCode} - {await response.Content.ReadAsStringAsync()}"); + { + throw new Exception($"{nameof(AccessToken)}.{nameof(GetAsync)} - Error getting access token - {response.StatusCode} - {await response.Content.ReadAsStringAsync()}"); } // Deserialize the access token from the response diff --git a/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/JWT.cs b/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/JWT.cs index 55d788a..8fc8ccc 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/JWT.cs +++ b/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/JWT.cs @@ -91,10 +91,10 @@ static private byte[] GetRSAPrivateKeyBytes(string certificateFilename, string c /// /// Get a security token descriptor /// - static private SecurityTokenDescriptor GetSecurityTokenDescriptor(byte[] keyBytes, + static private SecurityTokenDescriptor GetSecurityTokenDescriptor( + byte[] keyBytes, string? issuer, string? audience, bool expired, - // Dictionary claims, Dictionary claims, SecurityAlgorithm securityAlgorithm) { @@ -113,17 +113,6 @@ static private SecurityTokenDescriptor GetSecurityTokenDescriptor(byte[] keyByte tokenDescriptor.Expires = utcNow.AddSeconds(1); } - // Add claims - // tokenDescriptor.Subject = new ClaimsIdentity(); - // if (claims != null) - // { - // foreach (var kvp in claims) - // { - // // tokenDescriptor.Subject.AddClaim(new Claim(kvp.Key, kvp.Value)); - // tokenDescriptor.Subject.AddClaim(new Claim(kvp.Key, kvp.Value.ToString())); - // } - // } - tokenDescriptor.Claims = claims; // Signing credentials @@ -146,8 +135,12 @@ static private SecurityTokenDescriptor GetSecurityTokenDescriptor(byte[] keyByte /// static private RsaSecurityKey GetRsaSecurityKey(byte[] keyBytes) { - var key1 = CngKey.Import(keyBytes, CngKeyBlobFormat.Pkcs8PrivateBlob); - var rsa = new RSACng(key1); + var rsa = RSA.Create(); + rsa.ImportPkcs8PrivateKey(keyBytes, out _); + //rsa.ImportPkcs8PrivateKey(keyBytes, out _); + //var rsaSecurityKey = new RsaSecurityKey(rsa); + //var key1 = CngKey.Import(keyBytes, CngKeyBlobFormat.Pkcs8PrivateBlob); + //var rsa = new RSACng(key1); var kid = GetKeyId(rsa); var rsaSecurityKey = new RsaSecurityKey(rsa) diff --git a/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/PrivateKeyJwt.cs b/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/PrivateKeyJwt.cs index 26b5b50..f72c656 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/PrivateKeyJwt.cs +++ b/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/PrivateKeyJwt.cs @@ -99,9 +99,11 @@ public string Generate(string issuer, string audience) var privateKeyBytes = Convert.FromBase64String(PrivateKeyBase64); - using (var key = CngKey.Import(privateKeyBytes, CngKeyBlobFormat.Pkcs8PrivateBlob)) - using (var rsa = new RSACng(key)) - { + var rsa = RSA.Create(); + rsa.ImportPkcs8PrivateKey(privateKeyBytes, out _); + //using (var key = CngKey.Import(privateKeyBytes, CngKeyBlobFormat.Pkcs8PrivateBlob)) + //using (var rsa = new RSACng(key)) + //{ var kid = GenerateKeyId(rsa); var privateSecurityKey = new RsaSecurityKey(rsa) { @@ -127,7 +129,7 @@ public string Generate(string issuer, string audience) var tokenHandler = new JsonWebTokenHandler(); return tokenHandler.CreateToken(descriptor); - } + //} } /// @@ -135,12 +137,12 @@ public string Generate(string issuer, string audience) /// /// Raw private key /// Formatted private key - private string FormatKey(string privateKey) + private static string FormatKey(string privateKey) { return privateKey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r\n", "").Trim(); } - private string GenerateKeyId(RSAParameters rsaParams, out string e, out string n) + private static string GenerateKeyId(RSAParameters rsaParams, out string e, out string n) { e = Base64UrlEncoder.Encode(rsaParams.Exponent); n = Base64UrlEncoder.Encode(rsaParams.Modulus); @@ -159,7 +161,7 @@ private string GenerateKeyId(RSAParameters rsaParams, out string e, out string n /// /// RSA /// The generated kid value - private string GenerateKeyId(RSA rsa) + private static string GenerateKeyId(RSA rsa) { var rsaParameters = rsa.ExportParameters(false); return GenerateKeyId(rsaParameters, out _, out _); diff --git a/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/Untitled-1.jsonc b/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/Untitled-1.jsonc deleted file mode 100644 index 247b3aa..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/Infrastructure/Untitled-1.jsonc +++ /dev/null @@ -1,5 +0,0 @@ -{ - Microsoft.IdentityModel.Tokens.JsonWebKey, Use: 'sig', Kid: '73AEFCAF807652A46E3316DB47E905E7B72652B2', Kty: 'RSA', InternalId: 'ljDBpDqefCrHnn-5NWO-bn_8MXqFIDA86ddY5v0trcw'. -} - -"73AEFCAF807652A46E3316DB47E905E7B72652B2" \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/Properties/launchSettings.json b/Source/CDR.DataRecipient.IntegrationTests/Properties/launchSettings.json new file mode 100644 index 0000000..33504c9 --- /dev/null +++ b/Source/CDR.DataRecipient.IntegrationTests/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "WSL": { + "commandName": "WSL2", + "distributionName": "" + } + } +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/US12693_MDR_HostArrangementRevocation.cs b/Source/CDR.DataRecipient.IntegrationTests/US12693_MDR_HostArrangementRevocation.cs index 64ac560..43d679e 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/US12693_MDR_HostArrangementRevocation.cs +++ b/Source/CDR.DataRecipient.IntegrationTests/US12693_MDR_HostArrangementRevocation.cs @@ -1,15 +1,16 @@ +using CDR.DataRecipient.IntegrationTests.Fixtures; +using CDR.DataRecipient.IntegrationTests.Infrastructure.API2; +using CDR.DataRecipient.SDK.Models; +using FluentAssertions; +using FluentAssertions.Execution; +using Microsoft.Data.SqlClient; using System; using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; -using CDR.DataRecipient.SDK.Models; -using FluentAssertions; -using FluentAssertions.Execution; using Xunit; -using CDR.DataRecipient.IntegrationTests.Infrastructure.API2; -using Microsoft.Data.Sqlite; #nullable enable @@ -34,6 +35,8 @@ private class ConsentArrangement private static async Task Arrange(string? dataHolderBrandId = null) { + TestSetup.PatchRegister(); + // Get access token for Register async Task GetAccessTokenFromRegister() { @@ -70,7 +73,7 @@ async Task> GetDataHolderBrandsFromRegister(string token) HttpMethod = HttpMethod.Get, URL = REGISTER_MTLS_DATAHOLDERBRANDS_URL, AccessToken = token, - XV = "1" + XV = "2" }; var response = await apiCall.SendAsync(); @@ -86,23 +89,15 @@ async Task> GetDataHolderBrandsFromRegister(string token) return brandList ?? throw new Exception(); } - // Patch the seed data - // void PatchDataHolderBrands(List brandList) - // { - // var brand = brandList.Find(x => x.DataHolderBrandId == DATAHOLDER_BRAND.ToLower()) ?? throw new Exception("Brand not found"); - - // brand.EndpointDetail.InfoSecBaseUri = DATAHOLDER_BRAND_INFOSECBASEURL; - // } - // Save data holder brands void PersistDataHolderBrands(List brandList) { // Connect - using var connection = new SqliteConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); + using var connection = new SqlConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); connection.Open(); // Purge table - using var deleteCommand = new SqliteCommand($"delete from dataholderbrand", connection); + using var deleteCommand = new SqlCommand($"delete from dataholderbrand", connection); deleteCommand.ExecuteNonQuery(); // Save each brand @@ -110,14 +105,14 @@ void PersistDataHolderBrands(List brandList) { var jsonDocument = System.Text.Json.JsonSerializer.Serialize(brand); - using var insertCommand = new SqliteCommand($"insert into dataholderbrand (dataholderbrandid, jsondocument) values (@dataholderbrandid, @jsondocument)", connection); + using var insertCommand = new SqlCommand($"insert into dataholderbrand (dataholderbrandid, jsondocument) values (@dataholderbrandid, @jsondocument)", connection); insertCommand.Parameters.AddWithValue("@dataholderbrandid", brand.DataHolderBrandId); insertCommand.Parameters.AddWithValue("@jsondocument", jsonDocument); insertCommand.ExecuteNonQuery(); } // Check count - using var selectCommand = new SqliteCommand($"select count(*) from dataholderbrand", connection); + using var selectCommand = new SqlCommand($"select count(*) from dataholderbrand", connection); var count = Convert.ToInt32(selectCommand.ExecuteScalar()); if (count != brandList.Count) { @@ -126,30 +121,35 @@ void PersistDataHolderBrands(List brandList) } // Create and save a consent arrangement - string CreateConsentArrangement(string dataHolderBrandId) + string CreateConsentArrangement(string dataHolderBrandId, string clientId) { var consentArrangement = new ConsentArrangement { CdrArrangementId = Guid.NewGuid().ToString(), DataHolderBrandId = dataHolderBrandId, + ClientId = clientId, + ExpiresIn = 300, + CreatedOn = DateTime.Now, + SharingDuration = 0, }; // Connect - using var connection = new SqliteConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); + using var connection = new SqlConnection(BaseTest.DATARECIPIENT_CONNECTIONSTRING); connection.Open(); // Purge table - using var deleteCommand = new SqliteCommand($"delete from cdrarrangement", connection); + using var deleteCommand = new SqlCommand($"delete from cdrarrangement", connection); deleteCommand.ExecuteNonQuery(); // Save arrangement var jsonDocument = System.Text.Json.JsonSerializer.Serialize(consentArrangement); - using var insertCommand = new SqliteCommand($"insert into cdrarrangement (cdrarrangementid, jsondocument) values (@cdrarrangementid, @jsondocument)", connection); + using var insertCommand = new SqlCommand($"insert into cdrarrangement (cdrarrangementid, clientid, jsondocument) values (@cdrarrangementid, @clientid, @jsondocument)", connection); insertCommand.Parameters.AddWithValue("@cdrarrangementid", consentArrangement.CdrArrangementId); + insertCommand.Parameters.AddWithValue("@clientid", consentArrangement.ClientId); insertCommand.Parameters.AddWithValue("@jsondocument", jsonDocument); insertCommand.ExecuteNonQuery(); - using var selectCommand = new SqliteCommand($"select count(*) from cdrarrangement", connection); + using var selectCommand = new SqlCommand($"select count(*) from cdrarrangement", connection); var count = Convert.ToInt32(selectCommand.ExecuteScalar()); if (count != 1) { @@ -161,9 +161,8 @@ string CreateConsentArrangement(string dataHolderBrandId) var registerToken = await GetAccessTokenFromRegister(); var brandsList = await GetDataHolderBrandsFromRegister(registerToken); - // PatchDataHolderBrands(brandsList); PersistDataHolderBrands(brandsList); - return CreateConsentArrangement(dataHolderBrandId ?? DATAHOLDER_BRAND.ToLower()); + return CreateConsentArrangement(dataHolderBrandId ?? DATAHOLDER_BRAND.ToLower(), SOFTWAREPRODUCT_ID); } private static string GetClientAssertion() @@ -174,7 +173,7 @@ private static string GetClientAssertion() CertificatePassword = DATAHOLDER_CERTIFICATE_PASSWORD, Iss = DATAHOLDER_BRAND.ToLower(), Aud = DATARECIPIENT_ARRANGEMENTS_REVOKE_URL, - Kid = "73AEFCAF807652A46E3316DB47E905E7B72652B2", // Kid for this dataholder + Kid = "7C5716553E9B132EF325C49CA2079737196C03DB", // Kid for this dataholder }.Get(); } @@ -183,6 +182,7 @@ private static string GetClientAssertion() public async Task AC01_Post_WithCDRArrangementId_ShouldRespondWith_204NoContent(HttpStatusCode expectedStatusCode) { // Arrange + var clientAssertion = GetClientAssertion(); var cdrArrangementId = await Arrange(); var apiCall = new Infrastructure.API { @@ -190,7 +190,7 @@ public async Task AC01_Post_WithCDRArrangementId_ShouldRespondWith_204NoContent( CertificatePassword = DATAHOLDER_CERTIFICATE_PASSWORD, HttpMethod = HttpMethod.Post, URL = DATARECIPIENT_ARRANGEMENTS_REVOKE_URL, - AccessToken = GetClientAssertion(), + AccessToken = clientAssertion, Content = new FormUrlEncodedContent(new List> { new KeyValuePair("cdr_arrangement_id", cdrArrangementId) @@ -245,8 +245,7 @@ public async Task AC02_Post_WithInvalidCDRArrangementId_ShouldRespondWith_422Unp ""errors"": [{ ""code"": ""urn:au-cds:error:cds-all:Authorisation/InvalidArrangement"", ""title"": ""Invalid Consent Arrangement"", - ""detail"": """", - ""meta"": {} + ""detail"": ""Invalid arrangement: foo"" }] }"; await Assert_HasContent_Json(expectedContent, response.Content); @@ -261,6 +260,7 @@ public async Task AC03_Post_WithCDRArrangementIdNotOwnedByDataholder_ShouldRespo { // Arrange var cdrArrangementId = await Arrange(dataHolderBrandId); + var apiCall = new Infrastructure.API { CertificateFilename = DATAHOLDER_CERTIFICATE_FILENAME, @@ -290,10 +290,9 @@ public async Task AC03_Post_WithCDRArrangementIdNotOwnedByDataholder_ShouldRespo ""errors"": [{ ""code"": ""urn:au-cds:error:cds-all:Authorisation/InvalidArrangement"", ""title"": ""Invalid Consent Arrangement"", - ""detail"": """", - ""meta"": {} + ""detail"": ""Invalid arrangement: #{cdrArrangementId}"" }] - }"; + }".Replace("#{cdrArrangementId}", cdrArrangementId); await Assert_HasContent_Json(expectedContent, response.Content); } } @@ -335,8 +334,7 @@ public async Task AC04_Post_WithEmptyCDRArrangementId_ShouldRespondWith_400BadRe ""errors"": [{ ""code"": ""urn:au-cds:error:cds-all:Field/Missing"", ""title"": ""Missing Required Field"", - ""detail"": ""cdr_arrangement_id"", - ""meta"": {} + ""detail"": ""cdr_arrangement_jwt or cdr_arrangement_id"" }] }"; await Assert_HasContent_Json(expectedContent, response.Content); @@ -380,8 +378,7 @@ public async Task AC05_Post_WithInvalidContentTypeHeader_ShouldRespondWith_400Ba ""errors"": [{ ""code"": ""urn:au-cds:error:cds-all:Header/Invalid"", ""title"": ""Invalid Header"", - ""detail"": """", - ""meta"": {} + ""detail"": """" }] }"; await Assert_HasContent_Json(expectedContent, response.Content); diff --git a/Source/CDR.DataRecipient.IntegrationTests/US12964_MDR_Jwks.cs b/Source/CDR.DataRecipient.IntegrationTests/US12964_MDR_Jwks.cs index 5dd9868..e369218 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/US12964_MDR_Jwks.cs +++ b/Source/CDR.DataRecipient.IntegrationTests/US12964_MDR_Jwks.cs @@ -34,7 +34,7 @@ public async Task AC01_Get_ShouldRespondWith_200OK_ValidJWKS() var apiCall = new Infrastructure.API { HttpMethod = HttpMethod.Get, - URL = $"https://localhost:9001/jwks", + URL = $"https://{HOSTNAME_DATARECIPIENT}:9001/jwks", }; // Act diff --git a/Source/CDR.DataRecipient.IntegrationTests/appsettings.Container.json b/Source/CDR.DataRecipient.IntegrationTests/appsettings.Container.json new file mode 100644 index 0000000..3560b43 --- /dev/null +++ b/Source/CDR.DataRecipient.IntegrationTests/appsettings.Container.json @@ -0,0 +1,19 @@ +{ + "ConnectionStrings": { + "DataRecipient": "Server=mssql;Database=cdr-mdr;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True", + "Register": "Server=mssql;Database=cdr-register;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True" + }, + "Hostnames": { + "Register": "host.docker.internal", + "DataHolder": "host.docker.internal", + "DataRecipient": "host.docker.internal" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/appsettings.Development.json b/Source/CDR.DataRecipient.IntegrationTests/appsettings.Development.json new file mode 100644 index 0000000..5e882d5 --- /dev/null +++ b/Source/CDR.DataRecipient.IntegrationTests/appsettings.Development.json @@ -0,0 +1,20 @@ +{ + "ConnectionStrings": { + "DataRecipient": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-mdr;Integrated Security=true", + "Register": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-register;Integrated Security=true" + }, + "Hostnames": { + "Register": "localhost", + "DataHolder": "localhost", + "DataRecipient": "localhost" + }, + "Web_URL": "https://localhost:9001", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/appsettings.Pipeline.json b/Source/CDR.DataRecipient.IntegrationTests/appsettings.Pipeline.json deleted file mode 100644 index b424962..0000000 --- a/Source/CDR.DataRecipient.IntegrationTests/appsettings.Pipeline.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ConnectionStrings": { - "DataRecipient": "Data Source=D:\\a\\mock-data-recipient\\mock-data-recipient\\cdr\\mdr.db", - "Register": "Data Source=D:\\a\\mock-data-recipient\\mock-data-recipient\\cdr\\cdr.db" - } -} diff --git a/Source/CDR.DataRecipient.IntegrationTests/appsettings.Release.json b/Source/CDR.DataRecipient.IntegrationTests/appsettings.Release.json new file mode 100644 index 0000000..f93bb59 --- /dev/null +++ b/Source/CDR.DataRecipient.IntegrationTests/appsettings.Release.json @@ -0,0 +1,20 @@ +{ + "ConnectionStrings": { + "DataRecipient": "Server=mssql;Database=cdr-mdr;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True", + "Register": "Server=mssql;Database=cdr-register;User Id='SA';Password='Pa{}w0rd2019';MultipleActiveResultSets=True" + }, + "Hostnames": { + "Register": "mock-register", + "DataHolder": "mock-data-holder", + "DataRecipient": "mock-data-recipient" + }, + "Web_URL": "https://mock-data-recipient:9001", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/appsettings.json b/Source/CDR.DataRecipient.IntegrationTests/appsettings.json index 0ac802a..5e882d5 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/appsettings.json +++ b/Source/CDR.DataRecipient.IntegrationTests/appsettings.json @@ -1,14 +1,20 @@ { - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "ConnectionStrings": { - "DataRecipient": "Data Source=C:\\cdr\\mdr.db", - "Register": "Data Source=C:\\cdr\\cdr.db" + "ConnectionStrings": { + "DataRecipient": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-mdr;Integrated Security=true", + "Register": "Server=(localdb)\\MSSQLLocalDB;Database=cdr-register;Integrated Security=true" + }, + "Hostnames": { + "Register": "localhost", + "DataHolder": "localhost", + "DataRecipient": "localhost" + }, + "Web_URL": "https://localhost:9001", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" } + }, + "AllowedHosts": "*" } \ No newline at end of file diff --git a/Source/CDR.DataRecipient.IntegrationTests/integration.runsettings b/Source/CDR.DataRecipient.IntegrationTests/integration.runsettings index f1a32db..3f3f8b1 100644 --- a/Source/CDR.DataRecipient.IntegrationTests/integration.runsettings +++ b/Source/CDR.DataRecipient.IntegrationTests/integration.runsettings @@ -3,7 +3,7 @@ - Pipeline + Development